diff --git a/data/core.yaml b/data/core.yaml index b317df32a..476f165cf 100644 --- a/data/core.yaml +++ b/data/core.yaml @@ -297,6 +297,7 @@ en: cancel: Cancel changes: "{count} Changes" download_changes: Download osmChange file + errors: Errors warnings: Warnings modified: Modified deleted: Deleted diff --git a/modules/core/context.js b/modules/core/context.js index d4e65f4b3..626545886 100644 --- a/modules/core/context.js +++ b/modules/core/context.js @@ -7,7 +7,7 @@ import _isObject from 'lodash-es/isObject'; import _isString from 'lodash-es/isString'; import _map from 'lodash-es/map'; -// import mapcssParse from 'mapcss-parse'; +import { parse as parseMapCSS } from 'mapcss-parse'; import { dispatch as d3_dispatch } from 'd3-dispatch'; @@ -314,12 +314,6 @@ export function coreContext() { return features.hasHiddenConnections(entity, graph); }; - - /* Presets */ - var presets; - context.presets = function() { return presets; }; - context.overwritePresets = function(newPresets) { presets.overwrite(newPresets); }; - /* Map */ var map; context.map = function() { return map; }; @@ -457,14 +451,24 @@ 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.presets().areaKeys()); }); - // context.validationRules = function() { return validations; }; - // }); - // } + /* Presets */ + var presets; + presets = presetIndex(); + if (utilExternalPresets()) { + presets.fromExternal(); + } else { + presets.init(); + } + context.presets = function() { return presets; }; + + if (utilExternalValidationRules()) { + var validationsUrl = utilStringQs(window.location.hash).validations; + d3_text(validationsUrl, function (err, mapcss) { + if (err) return; + var validations = _map(parseMapCSS(mapcss), function(mapcssConfig) { return utilMapCSSRule(mapcssConfig, context); }); + context.validationRules = function() { return validations; }; + }); + } history = coreHistory(context); context.graph = history.graph; @@ -494,7 +498,6 @@ export function coreContext() { connection = services.osm; background = rendererBackground(context); features = rendererFeatures(context); - presets = presetIndex(); map = rendererMap(context); context.mouse = map.mouse; @@ -512,17 +515,9 @@ export function coreContext() { } }); + areaKeys = presets.areaKeys(); background.init(); features.init(); - - if (utilExternalPresets()) { - presets.fromExternal(); - } else { - presets.init(); - } - - areaKeys = presets.areaKeys(); - return utilRebind(context, dispatch, 'on'); } diff --git a/modules/presets/index.js b/modules/presets/index.js index 522882c48..aa1924032 100644 --- a/modules/presets/index.js +++ b/modules/presets/index.js @@ -186,6 +186,7 @@ export function presetIndex() { d3_json(presetsUrl, function(err, presets) { if (err) all.init(); all.overwrite(presets); + all.areaKeys(); }); return all; }; diff --git a/modules/ui/commit_warnings.js b/modules/ui/commit_warnings.js index 74174772a..2317fc9f5 100644 --- a/modules/ui/commit_warnings.js +++ b/modules/ui/commit_warnings.js @@ -5,6 +5,7 @@ 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) { @@ -24,7 +25,7 @@ export function uiCommitWarnings(context) { }, {}); _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'; diff --git a/modules/util/mapcss_rule.js b/modules/util/mapcss_rule.js index c413b895d..d2b3259de 100644 --- a/modules/util/mapcss_rule.js +++ b/modules/util/mapcss_rule.js @@ -1,7 +1,8 @@ import _isMatch from 'lodash-es/isMatch'; import _intersection from 'lodash-es/intersection'; +import { tagMap } from 'mapcss-parse'; -export function utilMapCSSRule(selector, areaKeys) { +export function utilMapCSSRule(selector, context) { var ruleChecks = { equals: function (tags) { return _isMatch(tags, selector.equals); @@ -63,7 +64,8 @@ export function utilMapCSSRule(selector, areaKeys) { }, // borrowed from Way#isArea() - inferGeometry: function (tagMap, areaKeys) { + inferGeometry: function (tagMap, context) { + var areaKeys = context.presets().areaKeys(); var lineKeys = { highway: { rest_area: true, @@ -108,7 +110,7 @@ export function utilMapCSSRule(selector, areaKeys) { if (entity.type === 'node' || entity.type === 'relation') { return selector.geometry === entity.type; } else if (entity.type === 'way') { - return 'area' === entity.geometry(graph); + return this.inferGeometry(tagMap(selector), context) === entity.geometry(graph); } }, findWarnings: function (entity, graph, warnings) { diff --git a/package.json b/package.json index 3f2f448fc..52c1ac628 100644 --- a/package.json +++ b/package.json @@ -36,6 +36,7 @@ "@mapbox/vector-tile": "^1.3.1", "diacritics": "1.3.0", "lodash-es": "4.17.10", + "mapcss-parse": "github:DigitalGlobe/mapcss-parse#12", "marked": "0.4.0", "node-diff3": "1.0.0", "osm-auth": "1.0.2", diff --git a/test/spec/util/mapcss_rule.js b/test/spec/util/mapcss_rule.js index 40a65f6fa..6c25c9e77 100644 --- a/test/spec/util/mapcss_rule.js +++ b/test/spec/util/mapcss_rule.js @@ -45,7 +45,7 @@ describe('iD.utilMapCSSRule', function() { ]; var rules = selectors.map(function(s) { return iD.utilMapCSSRule(s); }); it ('turns selector object in mapcssRule', function () { - var ruleKeys = ['ruleChecks', 'type','buildChecks','matches','geometryMatches','findWarnings']; + var ruleKeys = ['ruleChecks', 'type','buildChecks','matches', 'inferGeometry', 'geometryMatches','findWarnings']; rules.forEach(function(rule) { expect(Object.keys(rule)).to.eql(ruleKeys); }); @@ -246,6 +246,81 @@ describe('iD.utilMapCSSRule', function() { }); }); }); + describe('#inferGeometry', function() { + var amenityDerivedArea = { + selector: { + 'geometry': 'closedway', + 'presence': 'amenity', + 'positiveRegex': { amenity: ['^school$', '^healthcare$'] }, + 'error': 'amenity cannot be healthcare or school!' + }, + tagMap: { + amenity: [ 'school', 'healthcare' ] + } + }; + + var areaDerivedArea = { + selector: { + 'geometry': 'closedway', + 'equals': { area: 'yes' }, + }, + tagMap: { + amenity: [ 'school', 'healthcare' ], + area: [ 'yes' ] + } + }; + + var badAreaDerivedLine = { + selector: { + 'geometry': 'closedway', + 'equals': { 'area': 'no' } + }, + tagMap: { + area: ['no'] + } + }; + + var roundHouseRailwayDerivedArea = { + selector: { + 'geometry': 'closedway', + 'equals': { 'railway': 'roundhouse' } + }, + tagMap: { + railway: ['roundhouse'] + } + }; + + var justClosedWayDerivedLine = { + selector: { + 'geometry': 'closedway' + }, + tagMap: {} + }; + + var areaKeys = iD.Context().presets().areaKeys(); + var rule, geom; + + rule = iD.utilMapCSSRule(amenityDerivedArea.selector); + geom = rule.inferGeometry(amenityDerivedArea.tagMap, areaKeys); + expect(geom).to.be.eql('area'); + + rule = iD.utilMapCSSRule(areaDerivedArea.selector); + geom = rule.inferGeometry(areaDerivedArea.tagMap, areaKeys); + expect(geom).to.be.eql('area'); + + rule = iD.utilMapCSSRule(badAreaDerivedLine.selector); + geom = rule.inferGeometry(badAreaDerivedLine.tagMap); + expect(geom).to.be.eql('line'); + + rule = iD.utilMapCSSRule(roundHouseRailwayDerivedArea.selector); + geom = rule.inferGeometry(roundHouseRailwayDerivedArea.tagMap, areaKeys); + expect(geom).to.be.eql('area'); + + rule = iD.utilMapCSSRule(justClosedWayDerivedLine.selector); + geom = rule.inferGeometry(justClosedWayDerivedLine.tagMap); + expect(geom).to.be.eql('line'); + + }); describe('#findWarnings', function() { it('adds found warnings to warnings array', function() { var graph = iD.Graph([entities]); @@ -257,12 +332,12 @@ describe('iD.utilMapCSSRule', function() { }); }); - warnings.forEach(function(warning) { + // warnings.forEach(function(warning) { // console.log(warning); // expect(warning.message).to.not.be.null; // expect(['mapcss_warning', 'mapcss_error'].indexOf(warning.id)).to.be.greaterThan(-1); // expect(warning.entity).to.be.instanceOf(iD.Entity); - }); + // }); }); }); });