From 3e7146c63f3d6150ecbaa3a5d1c9c47deeff56a7 Mon Sep 17 00:00:00 2001 From: Thomas Hervey Date: Fri, 3 Aug 2018 15:35:49 -0500 Subject: [PATCH] WIP: menu with sub-layer buttons; TODO: bug fixes, ui updates, wiring buttons --- css/65_data.css | 193 +++++++- data/core.yaml | 436 +++++++++--------- dist/locales/en.json | 534 +++++++++++----------- modules/services/keepRight.js | 10 +- modules/svg/keepRight.js | 28 +- modules/ui/keepRight_details.js | 78 +++- modules/ui/keepRight_editor.js | 32 +- modules/ui/keepRight_header.js | 26 +- modules/ui/map_data.js | 82 ++++ modules/util/index.js | 2 +- modules/util/keepRight/errorSchema.json | 2 +- modules/util/keepRight/index.js | 4 +- modules/util/keepRight/keepRight_error.js | 67 +-- svg/iD-sprite/icons/icon-bolt.svg | 6 + svg/iD-sprite/icons/icon-keepRight.svg | 10 - 15 files changed, 949 insertions(+), 561 deletions(-) create mode 100644 svg/iD-sprite/icons/icon-bolt.svg delete mode 100644 svg/iD-sprite/icons/icon-keepRight.svg diff --git a/css/65_data.css b/css/65_data.css index b3c85e284..af60c2b66 100644 --- a/css/65_data.css +++ b/css/65_data.css @@ -25,10 +25,14 @@ .layer-keepRight .kr_error .kr_error-shadow { color: #000; } -.note-header-icon .note-fill, -.layer-notes .note .note-fill, + .kr_error-header-icon .kr_error-fill, .layer-keepRight .kr_error .kr_error-fill { + stroke: #333; +} + +.note-header-icon .note-fill, +.layer-notes .note .note-fill { color: #ff3300; stroke: #333; stroke-width: 40px; @@ -172,3 +176,188 @@ border-radius: 5px 0 0 5px; } +/* KeepRight */ + +.kr_error_type_30 { + color: #ddb87d; +} + +.kr_error_type_40, +.kr_error_type_41, +.kr_error_type_42, +.kr_error_type_43 { + color: #894668; +} + +.kr_error_type_50 { + color: #c827fe; +} + +.kr_error_type_70, +.kr_error_type_71, +.kr_error_type_72 { + color: #74aeaf; +} + +.kr_error_type_90 { + color: #3124af; +} + +.kr_error_type_100 { + color: #9e8e91; +} + +.kr_error_type_110 { + color: #44650b; +} + +.kr_error_type_120 { + color: #99274d; +} + +.kr_error_type_130 { + color: #eb7310; +} + +.kr_error_type_150 { + color: #7218c1; +} + +.kr_error_type_160 { + color: #c903ae; +} + +.kr_error_type_170 { + color: #07d40b; +} + +.kr_error_type_180 { + color: #09ef12; +} + +.kr_error_type_190, +.kr_error_type_191, +.kr_error_type_192, +.kr_error_type_193, +.kr_error_type_194, +.kr_error_type_195, +.kr_error_type_196, +.kr_error_type_197, +.kr_error_type_198 { + color: #e6fcb0; +} + +.kr_error_type_200, +.kr_error_type_201, +.kr_error_type_202, +.kr_error_type_203, +.kr_error_type_204, +.kr_error_type_205, +.kr_error_type_206, +.kr_error_type_207, +.kr_error_type_208 { + color: #71f264; +} + +.kr_error_type_210, +.kr_error_type_211, +.kr_error_type_212 { + color: #4a7601; +} + +.kr_error_type_220, +.kr_error_type_221 { + color: #ef7cf2; +} + +.kr_error_type_230, +.kr_error_type_231, +.kr_error_type_232 { + color: #5f775c; +} + +.kr_error_type_270 { + color: #2aaf92; +} + +.kr_error_type_280, +.kr_error_type_281, +.kr_error_type_282, +.kr_error_type_283, +.kr_error_type_284, +.kr_error_type_285 { + color: #5f47a0; +} + +.kr_error_type_290, +.kr_error_type_291, +.kr_error_type_292, +.kr_error_type_293, +.kr_error_type_294, +.kr_error_type_295, +.kr_error_type_296, +.kr_error_type_297, +.kr_error_type_298 { + color: #9bb2cd; +} + +.kr_error_type_310, +.kr_error_type_311, +.kr_error_type_312, +.kr_error_type_313 { + color: #0550e8; +} + +.kr_error_type_320 { + color: #28d9bb; +} + +.kr_error_type_350 { + color: #4d719c; +} + +.kr_error_type_370 { + color: #ff8fdf; +} + +.kr_error_type_380 { + color: #b3b465; +} + +.kr_error_type_400, +.kr_error_type_401, +.kr_error_type_402 { + color: #b20e36; +} + +.kr_error_type_410, +.kr_error_type_411, +.kr_error_type_412, +.kr_error_type_413 { + color: #b07f7e; +} + +.kr_error-details-description { + text-align: left; + margin-bottom: 20px; +} + +.kr_error-details-description { + text-align: left; +} + +.QA-buttons { + display: flex; + flex-flow: row nowrap; + justify-content: space-around; + align-items: center; + padding: 0 5px; +} + +.QA-toggle-off, +.QA-toggle-on { + width: 35%; + margin: 10px 0px; + text-align: center; + vertical-align: middle; +} diff --git a/data/core.yaml b/data/core.yaml index 838205268..2d2eeb0b9 100644 --- a/data/core.yaml +++ b/data/core.yaml @@ -486,6 +486,7 @@ en: zoom: Zoom to data fill_area: Fill Areas map_features: Map Features + QA: QA autohidden: "These features have been automatically hidden because too many would be shown on the screen. You can zoom in to edit them." osmhidden: "These features have been automatically hidden because the OpenStreetMap layer is hidden." feature: @@ -648,264 +649,265 @@ en: keepRight: Error - tooltip: Q/A data from keepright.at title: Edit Error + detail_title: Error + detail_description: Description inputPlaceholder: Enter a comment to share with other users. newComment: New Comment upload_explanation: Your comments will be publicly visible to all keepRight.at users. - upload_explanation_with_user: "Your comments as {user} will be publicly visible to all OpenStreetMap users." - close_comment: Close and Comment - open_comment: Reopen and Comment - close: Close Note - open: Reopen Note + upload_explanation_with_user: "Your comments as {user} will be publicly visible to all keepRight.at users." + resolve_comment: Comment and Resolve + ignore_comment: Comment and Ignore + resolve: Resolve + ignore: Ignore + toggle-on: All on + toggle-off: All off entities: node: node way: way relation: relation - highway: highway - cycleway: cycleway - waterway: waterway - types: + errorTypes: errors: _30: - title: 'non-closed_areas' - description: 'This way is tagged with {var1}={var2} and should be closed-loop' + description: 'non-closed_areas' + tooltip: 'This way is tagged with {var1}={var2} and should be closed-loop' _40: - title: 'dead-ended one-ways' - description: 'The first node (id {var1}) of this one-way is not connected to any other way' - _41: - title: '' - description: 'The last node (id {var1}) of this one-way is not connected to any other way' - _42: - title: '' - description: 'This node cannot be reached because one-ways only lead away from here' - _43: - title: '' - description: 'You cannot escape from this node because one-ways only lead to here' + description: 'dead-ended one-ways' + tooltip: 'The first node (id {var1}) of this one-way is not connected to any other way' + _41: + description: '' + tooltip: 'The last node (id {var1}) of this one-way is not connected to any other way' + _42: + description: '' + tooltip: 'This node cannot be reached because one-ways only lead away from here' + _43: + description: '' + tooltip: 'You cannot escape from this node because one-ways only lead to here' _50: - title: 'almost-junctions' - description: 'This node is very close but not connected to way #{var1}' + description: 'almost-junctions' + tooltip: 'This node is very close but not connected to way #{var1}' _70: - title: 'missing tags' - description: 'This {var1} has an empty tag: {var2}' - _71: - title: '' - description: 'This way has no tags' - _72: - title: '' - description: 'This node is not member of any way and doesn''t have any tags' + description: 'missing tags' + tooltip: 'This {var1} has an empty tag: {var2}' + _71: + description: '' + tooltip: 'This way has no tags' + _72: + description: '' + tooltip: 'This node is not member of any way and doesn''t have any tags' _90: - title: 'motorways without ref' - description: 'This way is tagged as motorway and therefore needs a ref nat_ref or int_ref tag' + description: 'motorways without ref' + tooltip: 'This way is tagged as motorway and therefore needs a ref nat_ref or int_ref tag' _100: - title: 'places of worship without religion' - description: 'This {var1} is tagged as place of worship and therefore needs a religion tag' + description: 'places of worship without religion' + tooltip: 'This {var1} is tagged as place of worship and therefore needs a religion tag' _110: - title: 'point of interest without name' - description: 'This node is tagged as {var1} and therefore needs a name tag' + description: 'point of interest without name' + tooltip: 'This node is tagged as {var1} and therefore needs a name tag' _120: - title: 'ways without nodes' - description: 'This way has just one single node' + description: 'ways without nodes' + tooltip: 'This way has just one single node' _130: - title: 'floating islands' - description: 'This way is not connected to the rest of the map' + description: 'floating islands' + tooltip: 'This way is not connected to the rest of the map' _150: - title: 'railway crossing without tag' - description: 'This crossing of a highway and a railway needs to be tagged as railway=crossing or railway=level_crossing' + description: 'railway crossing without tag' + tooltip: 'This crossing of a highway and a railway needs to be tagged as railway=crossing or railway=level_crossing' _160: - title: 'wrongly used railway tag' - description: 'There are ways in different layers coming together in this railway crossing. There are ways tagged as tunnel or bridge coming together in this railway crossing' + description: 'wrongly used railway tag' + tooltip: 'There are ways in different layers coming together in this railway crossing. There are ways tagged as tunnel or bridge coming together in this railway crossing' _170: - title: 'FIXME tagged items' - description: '{var1}' + description: 'FIXME tagged items' + tooltip: '{var1}' _180: - title: 'relations without type' - description: 'This relation has no type tag which is mandatory for relations' + description: 'relations without type' + tooltip: 'This relation has no type tag which is mandatory for relations' _190: - title: 'intersections without junctions' - description: 'Finds way crossings on same layer without common node as a junction' - _191: - title: 'highway-highway' - description: 'This {var1} intersects the {var2} #{var3} but there is no junction node' - _192: - title: 'highway-waterway' - description: 'This {var1} intersects the {var2} #{var3}' - _193: - title: 'highway-riverbank' - description: 'This {var1} intersects the {var2} #{var3}' - _194: - title: 'waterway-waterway' - description: 'This {var1} intersects the {var2} #{var3} but there is no junction node' - _195: - title: 'cycleway-cycleway' - description: 'This {var1} intersects the {var2} #{var3} but there is no junction node' - _196: - title: 'highway-cycleway' - description: 'This {var1} intersects the {var2} #{var3} but there is no junction node' - _197: - title: 'cycleway-waterway' - description: 'This {var1} intersects the {var2} #{var3}' - _198: - title: 'cycleway-riverbank' - description: 'This {var1} intersects the {var2} #{var3}' + description: 'intersections without junctions' + tooltip: 'Finds way crossings on same layer without common node as a junction' + _191: + description: 'highway-highway' + tooltip: 'This {var1} intersects the {var2} #{var3} but there is no junction node' + _192: + description: 'highway-waterway' + tooltip: 'This {var1} intersects the {var2} #{var3}' + _193: + description: 'highway-riverbank' + tooltip: 'This {var1} intersects the {var2} #{var3}' + _194: + description: 'waterway-waterway' + tooltip: 'This {var1} intersects the {var2} #{var3} but there is no junction node' + _195: + description: 'cycleway-cycleway' + tooltip: 'This {var1} intersects the {var2} #{var3} but there is no junction node' + _196: + description: 'highway-cycleway' + tooltip: 'This {var1} intersects the {var2} #{var3} but there is no junction node' + _197: + description: 'cycleway-waterway' + tooltip: 'This {var1} intersects the {var2} #{var3}' + _198: + description: 'cycleway-riverbank' + tooltip: 'This {var1} intersects the {var2} #{var3}' _200: - title: 'overlapping ways' - description: 'Finds overlapping ways on same layer' - _201: - title: 'highway-highway' - description: 'This {var1} overlaps the {var2} #{var3}' - _202: - title: 'highway-waterway' - description: 'This {var1} overlaps the {var2} #{var3}' - _203: - title: 'highway-riverbank' - description: 'This {var1} overlaps the {var2} #{var3}' - _204: - title: 'waterway-waterway' - description: 'This {var1} overlaps the {var2} #{var3}' - _205: - title: 'cycleway-cycleway' - description: 'This {var1} overlaps the {var2} #{var3}' - _206: - title: 'highway-cycleway' - description: 'This {var1} overlaps the {var2} #{var3}' - _207: - title: 'cycleway-waterway' - description: 'This {var1} overlaps the {var2} #{var3}' - _208: - title: 'cycleway-riverbank' - description: 'This {var1} overlaps the {var2} #{var3}' + description: 'overlapping ways' + tooltip: 'Finds overlapping ways on same layer' + _201: + description: 'highway-highway' + tooltip: 'This {var1} overlaps the {var2} #{var3}' + _202: + description: 'highway-waterway' + tooltip: 'This {var1} overlaps the {var2} #{var3}' + _203: + description: 'highway-riverbank' + tooltip: 'This {var1} overlaps the {var2} #{var3}' + _204: + description: 'waterway-waterway' + tooltip: 'This {var1} overlaps the {var2} #{var3}' + _205: + description: 'cycleway-cycleway' + tooltip: 'This {var1} overlaps the {var2} #{var3}' + _206: + description: 'highway-cycleway' + tooltip: 'This {var1} overlaps the {var2} #{var3}' + _207: + description: 'cycleway-waterway' + tooltip: 'This {var1} overlaps the {var2} #{var3}' + _208: + description: 'cycleway-riverbank' + tooltip: 'This {var1} overlaps the {var2} #{var3}' _210: - title: 'loopings' - description: 'These errors contain self intersecting ways' - _211: - title: '' - description: 'This way contains more than one node at least twice. Nodes are {var1}. This may or may not be an error' - _212: - title: '' - description: 'This way has only two different nodes and contains one of them more than once' + description: 'loopings' + tooltip: 'These errors contain self intersecting ways' + _211: + description: '' + tooltip: 'This way contains more than one node at least twice. Nodes are {var1}. This may or may not be an error' + _212: + description: '' + tooltip: 'This way has only two different nodes and contains one of them more than once' _220: - title: 'misspelled tags' - description: 'This {var1} is tagged {var2}={var3} where {var4} looks like {var5}' - _221: - title: '' - description: 'The key of this {var1} tag is key {var2}' - _230: - title: 'layer conflicts' - description: '' - _231: - title: 'mixed layers intersection' - description: 'This node is a junction of ways on different layers: {var1}' - _232: - title: 'strange layers' - description: 'This {var1} is tagged with layer {var2}. This need not be an error but it looks strange' + description: 'misspelled tags' + tooltip: 'This {var1} is tagged {var2}={var3} where {var4} looks like {var5}' + _221: + description: '' + tooltip: 'The key of this {var1} tag is key {var2}' + _230: + description: 'layer conflicts' + tooltip: '' + _231: + description: 'mixed layers intersection' + tooltip: 'This node is a junction of ways on different layers: {var1}' + _232: + description: 'strange layers' + tooltip: 'This {var1} is tagged with layer {var2}. This need not be an error but it looks strange' _270: - title: 'motorways connected directly' - description: 'This node is a junction of a motorway and a highway other than motorway, motorway_link, trunk, rest_area or construction. Service or unclassified is only valid if it has access=no/private or it leads to a motorway service area or if it is a service=parking_aisle.' + description: 'motorways connected directly' + tooltip: 'This node is a junction of a motorway and a highway other than motorway, motorway_link, trunk, rest_area or construction. Service or unclassified is only valid if it has access=no/private or it leads to a motorway service area or if it is a service=parking_aisle.' _280: - title: 'boundaries' - description: '' - _281: - title: 'missing name' - description: 'This boundary has no name' - _282: - title: 'missing admin level' - description: 'The boundary of {var1} has no valid numeric admin_level. Please do not use admin levels like for example 6;7. Always tag the lowest admin_level of all boundaries' - _283: - title: 'no closed loop' - description: 'The boundary of {var1} is not closed-loop' - _284: - title: 'splitting boundary' - description: 'The boundary of {var1} splits here' - _285: - title: 'admin_level too high' - description: 'This boundary-way has admin_level {var1} but belongs to a relation with lower admin_level (higher priority); it should have the lowest admin_level of all relations' + description: 'boundaries' + tooltip: '' + _281: + description: 'missing name' + tooltip: 'This boundary has no name' + _282: + description: 'missing admin level' + tooltip: 'The boundary of {var1} has no valid numeric admin_level. Please do not use admin levels like for example 6;7. Always tag the lowest admin_level of all boundaries' + _283: + description: 'no closed loop' + tooltip: 'The boundary of {var1} is not closed-loop' + _284: + description: 'splitting boundary' + tooltip: 'The boundary of {var1} splits here' + _285: + description: 'admin_level too high' + tooltip: 'This boundary-way has admin_level {var1} but belongs to a relation with lower admin_level (higher priority); it should have the lowest admin_level of all relations' _290: - title: 'restrictions' - description: 'Analyses all relations tagged type=restriction or following variations type=restriction:hgv type=restriction:caravan type=restriction:motorcar type=restriction:bus type=restriction:agricultural type=restriction:motorcycle type=restriction:bicycle and type=restriction:hazmat' - _291: - title: 'missing type' - description: 'This turn-restriction has no known restriction type' - _292: - title: 'missing from way' - description: 'A turn-restriction needs exactly one {var1} member. This one has {var2}' - _293: - title: 'missing to way' - description: 'A turn-restriction needs exactly one {var1} member. This one has {var2}' - _294: - title: 'from or to not a way' - description: 'From- and To-members of turn restrictions need to be ways. {var1}' - _295: - title: 'via is not on the way ends' - description: 'via (node #{var1}) is not the first or the last member of from (way #{var2})' - _296: - title: 'wrong restriction angle' - description: 'restriction type is {var1} but angle is {var2} degrees. Maybe the restriction type is not appropriate?' - _297: - title: 'wrong direction of to member' - description: 'wrong direction of to way {var1}' - _298: - title: 'already restricted by oneway' - description: 'entry already prohibited by oneway tag on {var1}' + description: 'restrictions' + tooltip: 'Analyses all relations tagged type=restriction or following variations type=restriction:hgv type=restriction:caravan type=restriction:motorcar type=restriction:bus type=restriction:agricultural type=restriction:motorcycle type=restriction:bicycle and type=restriction:hazmat' + _291: + description: 'missing type' + tooltip: 'This turn-restriction has no known restriction type' + _292: + description: 'missing from way' + tooltip: 'A turn-restriction needs exactly one {var1} member. This one has {var2}' + _293: + description: 'missing to way' + tooltip: 'A turn-restriction needs exactly one {var1} member. This one has {var2}' + _294: + description: 'from or to not a way' + tooltip: 'From- and To-members of turn restrictions need to be ways. {var1}' + _295: + description: 'via is not on the way ends' + tooltip: 'via (node #{var1}) is not the first or the last member of from (way #{var2})' + _296: + description: 'wrong restriction angle' + tooltip: 'restriction type is {var1} but angle is {var2} degrees. Maybe the restriction type is not appropriate?' + _297: + description: 'wrong direction of to member' + tooltip: 'wrong direction of to way {var1}' + _298: + description: 'already restricted by oneway' + tooltip: 'entry already prohibited by oneway tag on {var1}' _310: - title: 'roundabouts' - description: 'Analyses ways with tag junction=roundabout. More then one way can form a roundabout. It supports tag oneway=-1' - _311: - title: 'not closed loop' - description: 'This way is part of a roundabout but is not closed-loop. (split carriageways approaching a roundabout should not be tagged as roundabout)' - _312: - title: 'wrong direction' - description: 'If this roundabout is in a country with right-hand traffic then its orientation goes the wrong way around | If this roundabout is in a country with left-hand traffic then its orientation goes the wrong way around | If this mini_roundabout is in a country with right-hand traffic then its orientation goes the wrong way around | If this mini_roundabout is in a country with left-hand traffic then its orientation goes the wrong way around' - _313: - title: 'faintly connected' - description: 'This roundabout has only {var1} other roads connected. Roundabouts typically have three' + description: 'roundabouts' + tooltip: 'Analyses ways with tag junction=roundabout. More then one way can form a roundabout. It supports tag oneway=-1' + _311: + description: 'not closed loop' + tooltip: 'This way is part of a roundabout but is not closed-loop. (split carriageways approaching a roundabout should not be tagged as roundabout)' + _312: + description: 'wrong direction' + tooltip: 'If this roundabout is in a country with right-hand traffic then its orientation goes the wrong way around | If this roundabout is in a country with left-hand traffic then its orientation goes the wrong way around | If this mini_roundabout is in a country with right-hand traffic then its orientation goes the wrong way around | If this mini_roundabout is in a country with left-hand traffic then its orientation goes the wrong way around' + _313: + description: 'faintly connected' + tooltip: 'This roundabout has only {var1} other roads connected. Roundabouts typically have three' _320: - title: '*_link connections' - description: 'This way is tagged as highway={var1}_link but doesn''t have a connection to any other {var1} or {var1}_link' + description: '*_link connections' + tooltip: 'This way is tagged as highway={var1}_link but doesn''t have a connection to any other {var1} or {var1}_link' _350: - title: 'bridge-tags' - description: 'This bridge doesn''t have a tag in common with its surrounding ways that shows the purpose of this bridge. There should be one of these tags: {var1}' + description: 'bridge-tags' + tooltip: 'This bridge doesn''t have a tag in common with its surrounding ways that shows the purpose of this bridge. There should be one of these tags: {var1}' _370: - title: 'doubled places' - description: 'This node has tags in common with the surrounding way #{var1} and seems to be redundand | This node has tags in common with the surrounding way #{var1} (including the name {var2}) and seems to be redundand' + description: 'doubled places' + tooltip: 'This node has tags in common with the surrounding way #{var1} and seems to be redundand | This node has tags in common with the surrounding way #{var1} (including the name {var2}) and seems to be redundand' _380: - title: 'non-physical use of sport-tag' - description: 'This way is tagged {var1} but has no physical tag like e.g. leisure, building, amenity or highway' + description: 'non-physical use of sport-tag' + tooltip: 'This way is tagged {var1} but has no physical tag like e.g. leisure, building, amenity or highway' _400: - title: 'geometry glitches' - description: '' - _401: - title: 'missing turn restriction' - description: 'ways {var1} and {var2} join in a very sharp angle here and there is no oneway tag or turn restriction that prevents turning from way {var1} to {var2}' - _402: - title: 'impossible angles' - description: 'this way bends in a very sharp angle here' + description: 'geometry glitches' + tooltip: '' + _401: + description: 'missing turn restriction' + tooltip: 'ways {var1} and {var2} join in a very sharp angle here and there is no oneway tag or turn restriction that prevents turning from way {var1} to {var2}' + _402: + description: 'impossible angles' + tooltip: 'this way bends in a very sharp angle here' _410: - title: 'website' - description: 'Web pages are analyzed. Web page is defined by any of the following tags website=* url=* website:mobile=* contact:website=* contact:url=* image=* source:website=* or source:url=*' - _411: - title: 'http error' - description: 'The URL ({var1}) cannot be opened (HTTP status code {var2})' - _412: - title: 'domain hijacking' - description: 'Possible domain squatting: {var1}. Suspicious text is: "{var2}"' - _413: - title: 'non-match' - description: 'Content of the URL ({var1}) did not contain these keywords: ({var2})' + description: 'website' + tooltip: 'Web pages are analyzed. Web page is defined by any of the following tags website=* url=* website:mobile=* contact:website=* contact:url=* image=* source:website=* or source:url=*' + _411: + description: 'http error' + tooltip: 'The URL ({var1}) cannot be opened (HTTP status code {var2})' + _412: + description: 'domain hijacking' + tooltip: 'Possible domain squatting: {var1}. Suspicious text is: "{var2}"' + _413: + description: 'non-match' + tooltip: 'Content of the URL ({var1}) did not contain these keywords: ({var2})' warnings: _20: - title: 'multiple nodes on the same spot' - description: 'There is more than one node in this spot. Offending node IDs: {var1}' + description: 'multiple nodes on the same spot' + tooltip: 'There is more than one node in this spot. Offending node IDs: {var1}' _60: - title: 'depreciated tags' - description: 'This {var1} uses deprecated tag {var2}={var3}. Please use {var4} instead!' + description: 'depreciated tags' + tooltip: 'This {var1} uses deprecated tag {var2}={var3}. Please use {var4} instead!' _300: - title: 'missing maxspeed' - description: 'missing maxspeed tag' + description: 'missing maxspeed' + tooltip: 'missing maxspeed tag' _360: - title: 'language unknown' - description: 'It would be nice if this {var1} had an additional tag name:XX={var2} where XX shows the language of its name {var2}' + description: 'language unknown' + tooltip: 'It would be nice if this {var1} had an additional tag name:XX={var2} where XX shows the language of its name {var2}' _390: - title: 'missing tracktype' - description: This track doesn't have a tracktype + description: 'missing tracktype' + tooltip: This track doesn't have a tracktype streetside: tooltip: "Streetside photos from Microsoft" title: "Photo Overlay (Bing Streetside)" diff --git a/dist/locales/en.json b/dist/locales/en.json index aeb19ddc9..24dfbfc72 100644 --- a/dist/locales/en.json +++ b/dist/locales/en.json @@ -591,6 +591,7 @@ }, "fill_area": "Fill Areas", "map_features": "Map Features", + "QA": "QA", "autohidden": "These features have been automatically hidden because too many would be shown on the screen. You can zoom in to edit them.", "osmhidden": "These features have been automatically hidden because the OpenStreetMap layer is hidden." }, @@ -787,345 +788,346 @@ "keepRight": "Error -", "tooltip": "Q/A data from keepright.at", "title": "Edit Error", + "detail_title": "Error", + "detail_description": "Description", "inputPlaceholder": "Enter a comment to share with other users.", "newComment": "New Comment", "upload_explanation": "Your comments will be publicly visible to all keepRight.at users.", - "upload_explanation_with_user": "Your comments as {user} will be publicly visible to all OpenStreetMap users.", - "close_comment": "Close and Comment", - "open_comment": "Reopen and Comment", - "close": "Close Note", - "open": "Reopen Note", + "upload_explanation_with_user": "Your comments as {user} will be publicly visible to all keepRight.at users.", + "resolve_comment": "Comment and Resolve", + "ignore_comment": "Comment and Ignore", + "resolve": "Resolve", + "ignore": "Ignore", + "toggle-on": "All on", + "toggle-off": "All off", "entities": { "node": "node", "way": "way", - "relation": "relation", - "highway": "highway", - "cycleway": "cycleway", - "waterway": "waterway" + "relation": "relation" }, - "types": { + "errorTypes": { "errors": { "_30": { - "title": "non-closed_areas", - "description": "This way is tagged with {var1}={var2} and should be closed-loop" + "description": "non-closed_areas", + "tooltip": "This way is tagged with {var1}={var2} and should be closed-loop" }, "_40": { - "title": "dead-ended one-ways", - "description": "The first node (id {var1}) of this one-way is not connected to any other way", - "_41": { - "title": "", - "description": "The last node (id {var1}) of this one-way is not connected to any other way" - }, - "_42": { - "title": "", - "description": "This node cannot be reached because one-ways only lead away from here" - }, - "_43": { - "title": "", - "description": "You cannot escape from this node because one-ways only lead to here" - } + "description": "dead-ended one-ways", + "tooltip": "The first node (id {var1}) of this one-way is not connected to any other way" + }, + "_41": { + "description": "", + "tooltip": "The last node (id {var1}) of this one-way is not connected to any other way" + }, + "_42": { + "description": "", + "tooltip": "This node cannot be reached because one-ways only lead away from here" + }, + "_43": { + "description": "", + "tooltip": "You cannot escape from this node because one-ways only lead to here" }, "_50": { - "title": "almost-junctions", - "description": "This node is very close but not connected to way #{var1}" + "description": "almost-junctions", + "tooltip": "This node is very close but not connected to way #{var1}" }, "_70": { - "title": "missing tags", - "description": "This {var1} has an empty tag: {var2}", - "_71": { - "title": "", - "description": "This way has no tags" - }, - "_72": { - "title": "", - "description": "This node is not member of any way and doesn't have any tags" - } + "description": "missing tags", + "tooltip": "This {var1} has an empty tag: {var2}" + }, + "_71": { + "description": "", + "tooltip": "This way has no tags" + }, + "_72": { + "description": "", + "tooltip": "This node is not member of any way and doesn't have any tags" }, "_90": { - "title": "motorways without ref", - "description": "This way is tagged as motorway and therefore needs a ref nat_ref or int_ref tag" + "description": "motorways without ref", + "tooltip": "This way is tagged as motorway and therefore needs a ref nat_ref or int_ref tag" }, "_100": { - "title": "places of worship without religion", - "description": "This {var1} is tagged as place of worship and therefore needs a religion tag" + "description": "places of worship without religion", + "tooltip": "This {var1} is tagged as place of worship and therefore needs a religion tag" }, "_110": { - "title": "point of interest without name", - "description": "This node is tagged as {var1} and therefore needs a name tag" + "description": "point of interest without name", + "tooltip": "This node is tagged as {var1} and therefore needs a name tag" }, "_120": { - "title": "ways without nodes", - "description": "This way has just one single node" + "description": "ways without nodes", + "tooltip": "This way has just one single node" }, "_130": { - "title": "floating islands", - "description": "This way is not connected to the rest of the map" + "description": "floating islands", + "tooltip": "This way is not connected to the rest of the map" }, "_150": { - "title": "railway crossing without tag", - "description": "This crossing of a highway and a railway needs to be tagged as railway=crossing or railway=level_crossing" + "description": "railway crossing without tag", + "tooltip": "This crossing of a highway and a railway needs to be tagged as railway=crossing or railway=level_crossing" }, "_160": { - "title": "wrongly used railway tag", - "description": "There are ways in different layers coming together in this railway crossing. There are ways tagged as tunnel or bridge coming together in this railway crossing" + "description": "wrongly used railway tag", + "tooltip": "There are ways in different layers coming together in this railway crossing. There are ways tagged as tunnel or bridge coming together in this railway crossing" }, "_170": { - "title": "FIXME tagged items", - "description": "{var1}" + "description": "FIXME tagged items", + "tooltip": "{var1}" }, "_180": { - "title": "relations without type", - "description": "This relation has no type tag which is mandatory for relations" + "description": "relations without type", + "tooltip": "This relation has no type tag which is mandatory for relations" }, "_190": { - "title": "intersections without junctions", - "description": "Finds way crossings on same layer without common node as a junction", - "_191": { - "title": "highway-highway", - "description": "This {var1} intersects the {var2} #{var3} but there is no junction node" - }, - "_192": { - "title": "highway-waterway", - "description": "This {var1} intersects the {var2} #{var3}" - }, - "_193": { - "title": "highway-riverbank", - "description": "This {var1} intersects the {var2} #{var3}" - }, - "_194": { - "title": "waterway-waterway", - "description": "This {var1} intersects the {var2} #{var3} but there is no junction node" - }, - "_195": { - "title": "cycleway-cycleway", - "description": "This {var1} intersects the {var2} #{var3} but there is no junction node" - }, - "_196": { - "title": "highway-cycleway", - "description": "This {var1} intersects the {var2} #{var3} but there is no junction node" - }, - "_197": { - "title": "cycleway-waterway", - "description": "This {var1} intersects the {var2} #{var3}" - }, - "_198": { - "title": "cycleway-riverbank", - "description": "This {var1} intersects the {var2} #{var3}" - } + "description": "intersections without junctions", + "tooltip": "Finds way crossings on same layer without common node as a junction" + }, + "_191": { + "description": "highway-highway", + "tooltip": "This {var1} intersects the {var2} #{var3} but there is no junction node" + }, + "_192": { + "description": "highway-waterway", + "tooltip": "This {var1} intersects the {var2} #{var3}" + }, + "_193": { + "description": "highway-riverbank", + "tooltip": "This {var1} intersects the {var2} #{var3}" + }, + "_194": { + "description": "waterway-waterway", + "tooltip": "This {var1} intersects the {var2} #{var3} but there is no junction node" + }, + "_195": { + "description": "cycleway-cycleway", + "tooltip": "This {var1} intersects the {var2} #{var3} but there is no junction node" + }, + "_196": { + "description": "highway-cycleway", + "tooltip": "This {var1} intersects the {var2} #{var3} but there is no junction node" + }, + "_197": { + "description": "cycleway-waterway", + "tooltip": "This {var1} intersects the {var2} #{var3}" + }, + "_198": { + "description": "cycleway-riverbank", + "tooltip": "This {var1} intersects the {var2} #{var3}" }, "_200": { - "title": "overlapping ways", - "description": "Finds overlapping ways on same layer", - "_201": { - "title": "highway-highway", - "description": "This {var1} overlaps the {var2} #{var3}" - }, - "_202": { - "title": "highway-waterway", - "description": "This {var1} overlaps the {var2} #{var3}" - }, - "_203": { - "title": "highway-riverbank", - "description": "This {var1} overlaps the {var2} #{var3}" - }, - "_204": { - "title": "waterway-waterway", - "description": "This {var1} overlaps the {var2} #{var3}" - }, - "_205": { - "title": "cycleway-cycleway", - "description": "This {var1} overlaps the {var2} #{var3}" - }, - "_206": { - "title": "highway-cycleway", - "description": "This {var1} overlaps the {var2} #{var3}" - }, - "_207": { - "title": "cycleway-waterway", - "description": "This {var1} overlaps the {var2} #{var3}" - }, - "_208": { - "title": "cycleway-riverbank", - "description": "This {var1} overlaps the {var2} #{var3}" - } + "description": "overlapping ways", + "tooltip": "Finds overlapping ways on same layer" + }, + "_201": { + "description": "highway-highway", + "tooltip": "This {var1} overlaps the {var2} #{var3}" + }, + "_202": { + "description": "highway-waterway", + "tooltip": "This {var1} overlaps the {var2} #{var3}" + }, + "_203": { + "description": "highway-riverbank", + "tooltip": "This {var1} overlaps the {var2} #{var3}" + }, + "_204": { + "description": "waterway-waterway", + "tooltip": "This {var1} overlaps the {var2} #{var3}" + }, + "_205": { + "description": "cycleway-cycleway", + "tooltip": "This {var1} overlaps the {var2} #{var3}" + }, + "_206": { + "description": "highway-cycleway", + "tooltip": "This {var1} overlaps the {var2} #{var3}" + }, + "_207": { + "description": "cycleway-waterway", + "tooltip": "This {var1} overlaps the {var2} #{var3}" + }, + "_208": { + "description": "cycleway-riverbank", + "tooltip": "This {var1} overlaps the {var2} #{var3}" }, "_210": { - "title": "loopings", - "description": "These errors contain self intersecting ways", - "_211": { - "title": "", - "description": "This way contains more than one node at least twice. Nodes are {var1}. This may or may not be an error" - }, - "_212": { - "title": "", - "description": "This way has only two different nodes and contains one of them more than once" - } + "description": "loopings", + "tooltip": "These errors contain self intersecting ways" + }, + "_211": { + "description": "", + "tooltip": "This way contains more than one node at least twice. Nodes are {var1}. This may or may not be an error" + }, + "_212": { + "description": "", + "tooltip": "This way has only two different nodes and contains one of them more than once" }, "_220": { - "title": "misspelled tags", - "description": "This {var1} is tagged {var2}={var3} where {var4} looks like {var5}", - "_221": { - "title": "", - "description": "The key of this {var1} tag is key {var2}" - }, - "_230": { - "title": "layer conflicts", - "description": "" - }, - "_231": { - "title": "mixed layers intersection", - "description": "This node is a junction of ways on different layers: {var1}" - }, - "_232": { - "title": "strange layers", - "description": "This {var1} is tagged with layer {var2}. This need not be an error but it looks strange" - } + "description": "misspelled tags", + "tooltip": "This {var1} is tagged {var2}={var3} where {var4} looks like {var5}" + }, + "_221": { + "description": "", + "tooltip": "The key of this {var1} tag is key {var2}" + }, + "_230": { + "description": "layer conflicts", + "tooltip": "" + }, + "_231": { + "description": "mixed layers intersection", + "tooltip": "This node is a junction of ways on different layers: {var1}" + }, + "_232": { + "description": "strange layers", + "tooltip": "This {var1} is tagged with layer {var2}. This need not be an error but it looks strange" }, "_270": { - "title": "motorways connected directly", - "description": "This node is a junction of a motorway and a highway other than motorway, motorway_link, trunk, rest_area or construction. Service or unclassified is only valid if it has access=no/private or it leads to a motorway service area or if it is a service=parking_aisle." + "description": "motorways connected directly", + "tooltip": "This node is a junction of a motorway and a highway other than motorway, motorway_link, trunk, rest_area or construction. Service or unclassified is only valid if it has access=no/private or it leads to a motorway service area or if it is a service=parking_aisle." }, "_280": { - "title": "boundaries", - "description": "", - "_281": { - "title": "missing name", - "description": "This boundary has no name" - }, - "_282": { - "title": "missing admin level", - "description": "The boundary of {var1} has no valid numeric admin_level. Please do not use admin levels like for example 6;7. Always tag the lowest admin_level of all boundaries" - }, - "_283": { - "title": "no closed loop", - "description": "The boundary of {var1} is not closed-loop" - }, - "_284": { - "title": "splitting boundary", - "description": "The boundary of {var1} splits here" - }, - "_285": { - "title": "admin_level too high", - "description": "This boundary-way has admin_level {var1} but belongs to a relation with lower admin_level (higher priority); it should have the lowest admin_level of all relations" - } + "description": "boundaries", + "tooltip": "" + }, + "_281": { + "description": "missing name", + "tooltip": "This boundary has no name" + }, + "_282": { + "description": "missing admin level", + "tooltip": "The boundary of {var1} has no valid numeric admin_level. Please do not use admin levels like for example 6;7. Always tag the lowest admin_level of all boundaries" + }, + "_283": { + "description": "no closed loop", + "tooltip": "The boundary of {var1} is not closed-loop" + }, + "_284": { + "description": "splitting boundary", + "tooltip": "The boundary of {var1} splits here" + }, + "_285": { + "description": "admin_level too high", + "tooltip": "This boundary-way has admin_level {var1} but belongs to a relation with lower admin_level (higher priority); it should have the lowest admin_level of all relations" }, "_290": { - "title": "restrictions", - "description": "Analyses all relations tagged type=restriction or following variations type=restriction:hgv type=restriction:caravan type=restriction:motorcar type=restriction:bus type=restriction:agricultural type=restriction:motorcycle type=restriction:bicycle and type=restriction:hazmat", - "_291": { - "title": "missing type", - "description": "This turn-restriction has no known restriction type" - }, - "_292": { - "title": "missing from way", - "description": "A turn-restriction needs exactly one {var1} member. This one has {var2}" - }, - "_293": { - "title": "missing to way", - "description": "A turn-restriction needs exactly one {var1} member. This one has {var2}" - }, - "_294": { - "title": "from or to not a way", - "description": "From- and To-members of turn restrictions need to be ways. {var1}" - }, - "_295": { - "title": "via is not on the way ends", - "description": "via (node #{var1}) is not the first or the last member of from (way #{var2})" - }, - "_296": { - "title": "wrong restriction angle", - "description": "restriction type is {var1} but angle is {var2} degrees. Maybe the restriction type is not appropriate?" - }, - "_297": { - "title": "wrong direction of to member", - "description": "wrong direction of to way {var1}" - }, - "_298": { - "title": "already restricted by oneway", - "description": "entry already prohibited by oneway tag on {var1}" - } + "description": "restrictions", + "tooltip": "Analyses all relations tagged type=restriction or following variations type=restriction:hgv type=restriction:caravan type=restriction:motorcar type=restriction:bus type=restriction:agricultural type=restriction:motorcycle type=restriction:bicycle and type=restriction:hazmat" + }, + "_291": { + "description": "missing type", + "tooltip": "This turn-restriction has no known restriction type" + }, + "_292": { + "description": "missing from way", + "tooltip": "A turn-restriction needs exactly one {var1} member. This one has {var2}" + }, + "_293": { + "description": "missing to way", + "tooltip": "A turn-restriction needs exactly one {var1} member. This one has {var2}" + }, + "_294": { + "description": "from or to not a way", + "tooltip": "From- and To-members of turn restrictions need to be ways. {var1}" + }, + "_295": { + "description": "via is not on the way ends", + "tooltip": "via (node #{var1}) is not the first or the last member of from (way #{var2})" + }, + "_296": { + "description": "wrong restriction angle", + "tooltip": "restriction type is {var1} but angle is {var2} degrees. Maybe the restriction type is not appropriate?" + }, + "_297": { + "description": "wrong direction of to member", + "tooltip": "wrong direction of to way {var1}" + }, + "_298": { + "description": "already restricted by oneway", + "tooltip": "entry already prohibited by oneway tag on {var1}" }, "_310": { - "title": "roundabouts", - "description": "Analyses ways with tag junction=roundabout. More then one way can form a roundabout. It supports tag oneway=-1", - "_311": { - "title": "not closed loop", - "description": "This way is part of a roundabout but is not closed-loop. (split carriageways approaching a roundabout should not be tagged as roundabout)" - }, - "_312": { - "title": "wrong direction", - "description": "If this roundabout is in a country with right-hand traffic then its orientation goes the wrong way around | If this roundabout is in a country with left-hand traffic then its orientation goes the wrong way around | If this mini_roundabout is in a country with right-hand traffic then its orientation goes the wrong way around | If this mini_roundabout is in a country with left-hand traffic then its orientation goes the wrong way around" - }, - "_313": { - "title": "faintly connected", - "description": "This roundabout has only {var1} other roads connected. Roundabouts typically have three" - } + "description": "roundabouts", + "tooltip": "Analyses ways with tag junction=roundabout. More then one way can form a roundabout. It supports tag oneway=-1" + }, + "_311": { + "description": "not closed loop", + "tooltip": "This way is part of a roundabout but is not closed-loop. (split carriageways approaching a roundabout should not be tagged as roundabout)" + }, + "_312": { + "description": "wrong direction", + "tooltip": "If this roundabout is in a country with right-hand traffic then its orientation goes the wrong way around | If this roundabout is in a country with left-hand traffic then its orientation goes the wrong way around | If this mini_roundabout is in a country with right-hand traffic then its orientation goes the wrong way around | If this mini_roundabout is in a country with left-hand traffic then its orientation goes the wrong way around" + }, + "_313": { + "description": "faintly connected", + "tooltip": "This roundabout has only {var1} other roads connected. Roundabouts typically have three" }, "_320": { - "title": "*_link connections", - "description": "This way is tagged as highway={var1}_link but doesn't have a connection to any other {var1} or {var1}_link" + "description": "*_link connections", + "tooltip": "This way is tagged as highway={var1}_link but doesn't have a connection to any other {var1} or {var1}_link" }, "_350": { - "title": "bridge-tags", - "description": "This bridge doesn't have a tag in common with its surrounding ways that shows the purpose of this bridge. There should be one of these tags: {var1}" + "description": "bridge-tags", + "tooltip": "This bridge doesn't have a tag in common with its surrounding ways that shows the purpose of this bridge. There should be one of these tags: {var1}" }, "_370": { - "title": "doubled places", - "description": "This node has tags in common with the surrounding way #{var1} and seems to be redundand | This node has tags in common with the surrounding way #{var1} (including the name {var2}) and seems to be redundand" + "description": "doubled places", + "tooltip": "This node has tags in common with the surrounding way #{var1} and seems to be redundand | This node has tags in common with the surrounding way #{var1} (including the name {var2}) and seems to be redundand" }, "_380": { - "title": "non-physical use of sport-tag", - "description": "This way is tagged {var1} but has no physical tag like e.g. leisure, building, amenity or highway" + "description": "non-physical use of sport-tag", + "tooltip": "This way is tagged {var1} but has no physical tag like e.g. leisure, building, amenity or highway" }, "_400": { - "title": "geometry glitches", - "description": "", - "_401": { - "title": "missing turn restriction", - "description": "ways {var1} and {var2} join in a very sharp angle here and there is no oneway tag or turn restriction that prevents turning from way {var1} to {var2}" - }, - "_402": { - "title": "impossible angles", - "description": "this way bends in a very sharp angle here" - } + "description": "geometry glitches", + "tooltip": "" + }, + "_401": { + "description": "missing turn restriction", + "tooltip": "ways {var1} and {var2} join in a very sharp angle here and there is no oneway tag or turn restriction that prevents turning from way {var1} to {var2}" + }, + "_402": { + "description": "impossible angles", + "tooltip": "this way bends in a very sharp angle here" }, "_410": { - "title": "website", - "description": "Web pages are analyzed. Web page is defined by any of the following tags website=* url=* website:mobile=* contact:website=* contact:url=* image=* source:website=* or source:url=*", - "_411": { - "title": "http error", - "description": "The URL ({var1}) cannot be opened (HTTP status code {var2})" - }, - "_412": { - "title": "domain hijacking", - "description": "Possible domain squatting: {var1}. Suspicious text is: \"{var2}\"" - }, - "_413": { - "title": "non-match", - "description": "Content of the URL ({var1}) did not contain these keywords: ({var2})" - } + "description": "website", + "tooltip": "Web pages are analyzed. Web page is defined by any of the following tags website=* url=* website:mobile=* contact:website=* contact:url=* image=* source:website=* or source:url=*" + }, + "_411": { + "description": "http error", + "tooltip": "The URL ({var1}) cannot be opened (HTTP status code {var2})" + }, + "_412": { + "description": "domain hijacking", + "tooltip": "Possible domain squatting: {var1}. Suspicious text is: \"{var2}\"" + }, + "_413": { + "description": "non-match", + "tooltip": "Content of the URL ({var1}) did not contain these keywords: ({var2})" } }, "warnings": { "_20": { - "title": "multiple nodes on the same spot", - "description": "There is more than one node in this spot. Offending node IDs: {var1}" + "description": "multiple nodes on the same spot", + "tooltip": "There is more than one node in this spot. Offending node IDs: {var1}" }, "_60": { - "title": "depreciated tags", - "description": "This {var1} uses deprecated tag {var2}={var3}. Please use {var4} instead!" + "description": "depreciated tags", + "tooltip": "This {var1} uses deprecated tag {var2}={var3}. Please use {var4} instead!" }, "_300": { - "title": "missing maxspeed", - "description": "missing maxspeed tag" + "description": "missing maxspeed", + "tooltip": "missing maxspeed tag" }, "_360": { - "title": "language unknown", - "description": "It would be nice if this {var1} had an additional tag name:XX={var2} where XX shows the language of its name {var2}" + "description": "language unknown", + "tooltip": "It would be nice if this {var1} had an additional tag name:XX={var2} where XX shows the language of its name {var2}" }, "_390": { - "title": "missing tracktype", - "description": "This track doesn't have a tracktype" + "description": "missing tracktype", + "tooltip": "This track doesn't have a tracktype" } } } diff --git a/modules/services/keepRight.js b/modules/services/keepRight.js index 7bc6ddc2f..5a1e3dc5d 100644 --- a/modules/services/keepRight.js +++ b/modules/services/keepRight.js @@ -186,7 +186,7 @@ export default { }, - // get all cached notes covering the viewport + // get all cached errors covering the viewport keepRight: function(projection) { var viewport = projection.clipExtent(); var min = [viewport[0][0], viewport[1][1]]; @@ -202,20 +202,20 @@ export default { return _keepRightCache.keepRight[id]; }, - // replace a single note in the cache + // replace a single error in the cache replaceError: function(error) { if (!(error instanceof krError) || !error.id) return; - _keepRightCache.note[error.id] = error; + _keepRightCache.keepRight[error.id] = error; updateRtree(encodeErrorRtree(error), true); // true = replace return error; }, - // remove a single note from the cache + // remove a single error from the cache removeError: function(error) { if (!(error instanceof krError) || !error.id) return; - delete _keepRightCache.note[error.id]; + delete _keepRightCache.keepRight[error.id]; updateRtree(encodeErrorRtree(error), false); // false = remove }, }; \ No newline at end of file diff --git a/modules/svg/keepRight.js b/modules/svg/keepRight.js index fb0c76603..561bf6970 100644 --- a/modules/svg/keepRight.js +++ b/modules/svg/keepRight.js @@ -1,4 +1,3 @@ -import _some from 'lodash-es/some'; import _throttle from 'lodash-es/throttle'; import { select as d3_select } from 'd3-selection'; import { svgPointTransform } from './index'; @@ -16,6 +15,7 @@ export function svgKeepRight(projection, context, dispatch) { if (svgKeepRight.initialized) return; // run once svgKeepRight.enabled = false; svgKeepRight.initialized = true; + svgKeepRight.visibleErrors = [30]; } @@ -49,7 +49,7 @@ export function svgKeepRight(projection, context, dispatch) { function editOff() { - layer.selectAll('.icon-sign').remove(); + layer.selectAll('.kr_error').remove(); layer.style('display', 'none'); } @@ -83,9 +83,10 @@ export function svgKeepRight(projection, context, dispatch) { var service = getService(); var selectedID = context.selectedNoteID(); // TODO: update with selectedErrorID var data = (service ? service.keepRight(projection) : []); + var visibleData = data; // getVisible(data); // TODO: only show sub-layers that are toggled on var transform = svgPointTransform(projection); var kr_errors = layer.selectAll('.kr_error') - .data(data, function(d) { return d.id; }); + .data(visibleData, function(d) { return d.id; }); // exit kr_errors.exit() @@ -94,7 +95,8 @@ export function svgKeepRight(projection, context, dispatch) { // enter var kr_errorsEnter = kr_errors.enter() .append('g') - .attr('class', function(d) { return 'kr_error kr_error-' + d.id; }) + .attr('class', function(d) { + return 'kr_error kr_error-' + d.id + ' kr_error_type_' + d.error_type; }) .classed('new', function(d) { return d.id < 0; }); kr_errorsEnter @@ -114,9 +116,9 @@ export function svgKeepRight(projection, context, dispatch) { .attr('class', 'kr_error-fill') .attr('width', '20px') .attr('height', '20px') - .attr('x', '-8px') - .attr('y', '-22px') - .attr('xlink:href', '#iD-icon-note'); // TODO: update icon + .attr('x', '-4px') + .attr('y', '-24px') + .attr('xlink:href', '#iD-icon-bolt'); // update kr_errors @@ -179,8 +181,16 @@ export function svgKeepRight(projection, context, dispatch) { }; - drawKeepRight.supported = function() { - return !!getService(); + drawKeepRight.visibleErrors = function(_) { + if (!arguments.length) return svgKeepRight.visibleErrors; + svgKeepRight.visibleErrors.push(_); + if (svgKeepRight.visibleErrors) { + showLayer(); + } else { + hideLayer(); + } + dispatch.call('change'); + return this; }; diff --git a/modules/ui/keepRight_details.js b/modules/ui/keepRight_details.js index 461da3f19..646609b61 100644 --- a/modules/ui/keepRight_details.js +++ b/modules/ui/keepRight_details.js @@ -1,12 +1,46 @@ import { t } from '../util/locale'; -import { utilGetErrorDetails } from '../util'; +import { parseErrorDescriptions, errorTypes } from '../util'; export function uiKeepRightDetails() { var _error; + var _template; + var _templateErrorType; + var _category; + var _categoryElements; + var _parent_error_type = ''; + var _titleBase; + + + function initDetails() { + if (errorTypes.errors['_' + _error.error_type]) { + _templateErrorType = '_' + _error.error_type; + _template = errorTypes.errors[_templateErrorType]; + _category = 'errors'; + } else if (errorTypes.warnings[_templateErrorType]) { + _template = errorTypes.errors[_templateErrorType]; + _category = 'warnings'; + } else { return; } + + // if there is a parent, save it's error type + _categoryElements = errorTypes[_category]; + var base_error_type = (Math.round(_error.error_type / 10) * 10).toString(); + if ((_categoryElements['_' + base_error_type]) && (base_error_type !== _error.error_type) ) { + _parent_error_type = '_' + base_error_type; + } + + _titleBase = 'keepRight.errorTypes.' + _category + '.'; + + } function keepRightDetails(selection) { + if (!_error || !_error.error_type) return; + + initDetails(); + if (!_template) return; + + var details = selection.selectAll('.kr_error-details') .data( (_error ? [_error] : []), @@ -18,14 +52,46 @@ export function uiKeepRightDetails() { var detailsEnter = details.enter() .append('div') - .attr('class', 'kr_error-details'); + .attr('class', 'kr_error-details kr_error-details-container'); - detailsEnter + // title + var title = detailsEnter + .append('div') + .attr('class', 'kr_error-details-title'); + + title.append('h4') + .text(function() { return t('keepRight.detail_title'); }); + + title.append('div') + .text(function() { + var title = ''; + + // if this is a subtype, append it's parent title + if (_parent_error_type) { + title = t(_titleBase + _parent_error_type + '.description' + ':\n'); + } + + // append title + if (_error.error_type) { + title += t(_titleBase + _templateErrorType + '.description'); + } + + return title; + }); + + // description + var description = detailsEnter + .append('div') + .attr('class', 'kr_error-details-description'); + + description + .append('h4') + .text(function() { return t('keepRight.detail_description'); }); + + description .append('div') - .attr('class', 'kr_error-details-label') .text(function(d) { - var error = utilGetErrorDetails(d); - return t('keepRight.keepRight'); // TODO: add details here + return t(_titleBase + _templateErrorType + '.tooltip', parseErrorDescriptions(d)); }); } diff --git a/modules/ui/keepRight_editor.js b/modules/ui/keepRight_editor.js index d7054f0a6..9002dc4ba 100644 --- a/modules/ui/keepRight_editor.js +++ b/modules/ui/keepRight_editor.js @@ -26,7 +26,7 @@ export function uiKeepRightEditor(context) { var dispatch = d3_dispatch('change'); var keepRightComment = uiKeepRightComment(); var keepRightDetails = uiKeepRightDetails(); - var keepRightHeader = uiKeepRightHeader(); + var keepRightHeader = uiKeepRightHeader(context); var _error; @@ -249,7 +249,11 @@ export function uiKeepRightEditor(context) { buttonEnter .append('button') - .attr('class', 'button status-button action'); + .attr('class', 'button resolve-button action'); + + buttonEnter + .append('button') + .attr('class', 'button ignore-button action'); buttonEnter .append('button') @@ -287,12 +291,28 @@ export function uiKeepRightEditor(context) { } }); - buttonSection.select('.status-button') // select and propagate data + buttonSection.select('.resolve-button') // select and propagate data .attr('disabled', (hasAuth ? null : true)) .text(function(d) { - var action = (d.status === 'open' ? 'close' : 'open'); // TODO: possibly remove reopen since I don't think it's an option var andComment = (d.newComment ? '_comment' : ''); - return t('keepRight.' + action + andComment); + return t('keepRight.resolve' + andComment); + }) + .on('click.status', function(d) { + this.blur(); // avoid keeping focus on the button - #4641 + var keepRight = services.keepRight; + if (keepRight) { + // TODO: handle posting updates + // keepRight.postKeepRightUpdate(d, function(err, error) { + // dispatch.call('change', error); + // }); + } + }); + + buttonSection.select('.ignore-button') // select and propagate data + .attr('disabled', (hasAuth ? null : true)) + .text(function(d) { + var andComment = (d.newComment ? '_comment' : ''); + return t('keepRight.ignore' + andComment); }) .on('click.status', function(d) { this.blur(); // avoid keeping focus on the button - #4641 @@ -307,7 +327,7 @@ export function uiKeepRightEditor(context) { buttonSection.select('.comment-button') // select and propagate data .attr('disabled', function(d) { - return (hasAuth && d.status === 'open' && d.newComment) ? null : true; + return (hasAuth && d.newComment) ? null : true; }) .on('click.comment', function(d) { this.blur(); // avoid keeping focus on the button - #4641 diff --git a/modules/ui/keepRight_header.js b/modules/ui/keepRight_header.js index 6fbbfdd4a..e98282725 100644 --- a/modules/ui/keepRight_header.js +++ b/modules/ui/keepRight_header.js @@ -2,15 +2,21 @@ import { t } from '../util/locale'; import { svgIcon } from '../svg'; -export function uiKeepRightHeader() { +export function uiKeepRightHeader(context) { var _error; + function getEntityLink() { + + var url = context.connection().entityURL(context.entity(_error.object_id)); + } + + function keepRightHeader(selection) { var header = selection.selectAll('.kr_error-header') .data( (_error ? [_error] : []), - function(d) { return d.status + d.id; } + function(d) { return d.id; } ); header.exit() @@ -22,20 +28,26 @@ export function uiKeepRightHeader() { var iconEnter = headerEnter .append('div') - .attr('class', function(d) { return 'kr_error-header-icon ' + d.status; }) + .attr('class', function(d) { return 'kr_error-header-icon '; }) .classed('new', function(d) { return d.id < 0; }); iconEnter .append('div') - .attr('class', 'preset-icon-28') - .call(svgIcon('#iD-icon-note', 'note-fill')); // TODO: change classes + .attr('class', function(d) { + return 'preset-icon-28 kr_error kr_error-' + d.id + ' kr_error_type_' + d.error_type; + }) + + .call(svgIcon('#iD-icon-bolt', 'kr_error-fill')); headerEnter .append('div') .attr('class', 'kr_error-header-label') .text(function(d) { - return t('keepRight.keepRight') + ' ' + d.object_type + ' ' + ' ' + d.error_id; - }); + return t('keepRight.entities.' + d.object_type); + }) + .append('div') + // .attr('href', getEntityLink()) // TODO: add / remove link if entity is/isn't in the graph + .text(function(d) { return d.object_id; }); } diff --git a/modules/ui/map_data.js b/modules/ui/map_data.js index b6fbe8a4b..1132957c2 100644 --- a/modules/ui/map_data.js +++ b/modules/ui/map_data.js @@ -1,9 +1,11 @@ +import { dispatch as d3_dispatch } from 'd3-dispatch'; import { event as d3_event, select as d3_select } from 'd3-selection'; import { svgIcon } from '../svg'; +import { errorTypes } from '../util'; import { t, textDirection } from '../util/locale'; import { tooltip } from '../util/tooltip'; import { geoExtent } from '../geo'; @@ -16,8 +18,11 @@ import { uiTooltipHtml } from './tooltipHtml'; export function uiMapData(context) { + var dispatch = d3_dispatch('change'); + var key = t('map_data.key'); var features = context.features().keys(); + var errors = Object.keys(errorTypes.errors); // TODO: add warnings var layers = context.layers(); var fills = ['wireframe', 'partial', 'full']; @@ -29,6 +34,7 @@ export function uiMapData(context) { var _dataLayerContainer = d3_select(null); var _fillList = d3_select(null); var _featureList = d3_select(null); + var _QAList = d3_select(null); function showsFeature(d) { @@ -47,6 +53,17 @@ export function uiMapData(context) { } + function showsError(d) { + // return context.errors().enabled(d); + } + + + function clickError(d) { + // context.errors().toggle(d); + // update(); + } + + function showsFill(d) { return _fillSelected === d; } @@ -411,6 +428,43 @@ export function uiMapData(context) { } + function drawQAButtons(selection) { + var QAButtons = d3_select('.layer-QA').selectAll('li').select('label').select('input'); + var buttonSection = selection.selectAll('.QA-buttons') + .data([0]); + + // exit + buttonSection.exit() + .remove(); + + // enter + var buttonEnter = buttonSection.enter() + .append('div') + .attr('class', 'QA-buttons'); + + buttonEnter + .append('button') + .attr('class', 'button QA-toggle-on action') + .text(t('keepRight.toggle-on')) + .on('click', function() { + QAButtons.property('checked', true); + dispatch.call('change'); + }); + + buttonEnter + .append('button') + .attr('class', 'button QA-toggle-off action') + .text(t('keepRight.toggle-off')) + .on('click', function() { + QAButtons.property('checked', false); + dispatch.call('change'); + }); + + buttonSection = buttonSection + .merge(buttonEnter); + } + + function drawListItems(selection, data, type, name, change, active) { var items = selection.selectAll('li') .data(data); @@ -498,6 +552,17 @@ export function uiMapData(context) { } + function renderQA(selection) { + var container = selection.selectAll('layer-QA') + .data([0]); + + _QAList = container.enter() + .append('ul') + .attr('class', 'layer-list layer-QA') + .merge(container); + } + + function update() { _dataLayerContainer .call(drawOsmItems) @@ -510,6 +575,11 @@ export function uiMapData(context) { _featureList .call(drawListItems, features, 'checkbox', 'feature', clickFeature, showsFeature); + + _QAList + .call(drawListItems, errors, 'checkbox', 'keepRight.errorTypes.errors', clickError, showsError); + d3_select('.disclosure-wrap-QA') + .call(drawQAButtons); } @@ -636,11 +706,23 @@ export function uiMapData(context) { .content(renderFeatureList) ); + // Q/A tools + content + .append('div') + .attr('class', 'map-data-QA') + .call(uiDisclosure(context, 'QA', false) + .title(t('map_data.QA')) + .content(renderQA) + ); + // add listeners context.features() .on('change.map_data-update', update); + // context.errors() + // .on('change.map_data-update', update); // TODO: add errors list to context? + update(); setFill(_fillSelected); diff --git a/modules/util/index.js b/modules/util/index.js index acf73b74c..be877351f 100644 --- a/modules/util/index.js +++ b/modules/util/index.js @@ -13,7 +13,7 @@ export { utilExternalValidationRules } from './util'; export { utilFastMouse } from './util'; export { utilFunctor } from './util'; export { utilGetAllNodes } from './util'; -export { utilGetErrorDetails } from './keepRight'; +export { errorTypes, parseErrorDescriptions } from './keepRight'; export { utilGetPrototypeOf } from './util'; export { utilGetSetValue } from './get_set_value'; export { utilHashcode } from './util'; diff --git a/modules/util/keepRight/errorSchema.json b/modules/util/keepRight/errorSchema.json index 00bb2d993..c6688d9d2 100644 --- a/modules/util/keepRight/errorSchema.json +++ b/modules/util/keepRight/errorSchema.json @@ -1,6 +1,6 @@ { - "types": { + "errorTypes": { "errors": { "_30": { "title": "non-closed_areas", diff --git a/modules/util/keepRight/index.js b/modules/util/keepRight/index.js index b14eacd63..4a95afaf5 100644 --- a/modules/util/keepRight/index.js +++ b/modules/util/keepRight/index.js @@ -1,2 +1,2 @@ -export { utilGetErrorDetails } from './keepRight_error'; -export { types } from './errorSchema.json'; \ No newline at end of file +export { parseErrorDescriptions } from './keepRight_error'; +export { errorTypes } from './errorSchema.json'; \ No newline at end of file diff --git a/modules/util/keepRight/keepRight_error.js b/modules/util/keepRight/keepRight_error.js index 2c07cb443..683b0ebee 100644 --- a/modules/util/keepRight/keepRight_error.js +++ b/modules/util/keepRight/keepRight_error.js @@ -1,7 +1,9 @@ +import { t } from '../locale'; import { krError } from '../../osm'; -import { types } from './errorSchema.json'; +import { errorTypes } from './errorSchema.json'; +// TODO: remove these objects, here for reference var keepRightSchema = { 'schema': '', 'id': 0, @@ -46,50 +48,57 @@ var keepRightSchemaFromWeb = { 'title': 'intersections without junctions, highway-waterway' }; -export function utilGetErrorDetails(entity) { +// TODO: clean up description parsing some: remove or ignore spurious characters +export function parseErrorDescriptions(entity) { if (!(entity instanceof krError)) return; // find the matching template from the error schema var errorType = '_' + entity.error_type; - var matchingTemplate = types.errors[errorType] || types.warnings[errorType]; + var matchingTemplate = errorTypes.errors[errorType] || errorTypes.warnings[errorType]; if (!matchingTemplate) return; // tokenize descriptions var errorDescriptions = entity.description.split(' '); - var schemaDescriptions = matchingTemplate.description.split(' '); + var templateDescriptions = matchingTemplate.description.split(' '); + var parsedDescriptions = []; + var re = new RegExp(/{\$[0-9]}/); - function iterator() { + var commonEntities = ['node', 'way', 'relation']; // TODO: expand this list, or implement a different translation function - var parsedDescription = []; - var re = new RegExp(/{\$[0-9]}/); + templateDescriptions.forEach(function(word, index) { + if (!re.test(word)) return; - schemaDescriptions.forEach(function(word, index) { // TODO: figure out how to get the word and the index in a foreach - if (!re.test(word)) return; + // get the word at this index, and at the next index value + var nextWord = templateDescriptions[index + 1] ? templateDescriptions[index + 1] : null; - // get the word at this index, and at the next index value - var nextWord = schemaDescriptions[index + 1] ? schemaDescriptions[index + 1] : null; + var parsedPhrase = ''; - // also get the word at the same index from the errorDescription + // parse error description words + for (var i = index; i <= errorDescriptions.length - 1; i++) { + if (errorDescriptions[i] !== nextWord) { + var currWord = errorDescriptions[i]; - var parsedPhrase = ''; - - - // while error terms do not equal the next schema term - for (var i = index; i <= errorDescriptions.length - 1; i++) { - if (errorDescriptions[i] !== nextWord) { - parsedPhrase += errorDescriptions[i]; + // if any variables contain common words, like node, way, relation, translate those + if (commonEntities.includes(currWord)) { + currWord = t('keepRight.entities.' + currWord); } - parsedDescription.push(parsedPhrase); - break; + + parsedPhrase += currWord; } - }); - } + // add phrase (or single word) to variable list + parsedDescriptions.push(parsedPhrase); + break; + } + }); - function getCommonWords() { // TODO: implement, see if a variable is a common word like 'node', so that we can translate it before sending it off - } - - - iterator(); -} \ No newline at end of file + return { + var1: parsedDescriptions[0] || '', + var2: parsedDescriptions[1] || '', + var3: parsedDescriptions[2] || '', + var4: parsedDescriptions[3] || '', + var5: parsedDescriptions[4] || '', + var6: parsedDescriptions[4] || '', + }; +} diff --git a/svg/iD-sprite/icons/icon-bolt.svg b/svg/iD-sprite/icons/icon-bolt.svg new file mode 100644 index 000000000..129fa8ac7 --- /dev/null +++ b/svg/iD-sprite/icons/icon-bolt.svg @@ -0,0 +1,6 @@ + + + + + diff --git a/svg/iD-sprite/icons/icon-keepRight.svg b/svg/iD-sprite/icons/icon-keepRight.svg deleted file mode 100644 index 0498225bb..000000000 --- a/svg/iD-sprite/icons/icon-keepRight.svg +++ /dev/null @@ -1,10 +0,0 @@ - - - - - -