From f7652b8858ebc786cf885de4ba3e2808fe0c22d2 Mon Sep 17 00:00:00 2001 From: John Firebaugh Date: Tue, 19 Mar 2013 14:33:29 -0700 Subject: [PATCH 01/10] Remove unused --- data/presets/presets.json | 8 -------- data/presets/presets/building.json | 8 -------- js/id/presets/preset.js | 1 - 3 files changed, 17 deletions(-) diff --git a/data/presets/presets.json b/data/presets/presets.json index 4406b34c8..19c987d0e 100644 --- a/data/presets/presets.json +++ b/data/presets/presets.json @@ -828,14 +828,6 @@ "building_yes", "levels" ], - "additional": [ - "address", - "phone", - "website", - "wikipedia", - "elevation", - "source" - ], "geometry": [ "area" ], diff --git a/data/presets/presets/building.json b/data/presets/presets/building.json index 13b7c32dc..daa8a2cb5 100644 --- a/data/presets/presets/building.json +++ b/data/presets/presets/building.json @@ -4,14 +4,6 @@ "building_yes", "levels" ], - "additional": [ - "address", - "phone", - "website", - "wikipedia", - "elevation", - "source" - ], "geometry": [ "area" ], diff --git a/js/id/presets/preset.js b/js/id/presets/preset.js index 477c13777..8b8ba456f 100644 --- a/js/id/presets/preset.js +++ b/js/id/presets/preset.js @@ -3,7 +3,6 @@ iD.presets.Preset = function(id, preset, fields) { preset.id = id; preset.fields = (preset.fields || []).map(getFields); - preset.additional = (preset.additional || []).map(getFields); function getFields(f) { return fields[f]; From 53820dc75d3d527e7ef1d775f5f55e68819cb0fb Mon Sep 17 00:00:00 2001 From: John Firebaugh Date: Tue, 19 Mar 2013 15:00:35 -0700 Subject: [PATCH 02/10] Validate preset json (fixes #1042) --- build.js | 28 +++++++++++++- data/presets/schema/field.json | 67 +++++++++++++++++++++++++++++++++ data/presets/schema/preset.json | 55 +++++++++++++++++++++++++++ package.json | 3 +- 4 files changed, 151 insertions(+), 2 deletions(-) create mode 100644 data/presets/schema/field.json create mode 100644 data/presets/schema/preset.json diff --git a/build.js b/build.js index 7f77b6de1..e05dd40e2 100644 --- a/build.js +++ b/build.js @@ -2,7 +2,10 @@ var fs = require('fs'), path = require('path'), glob = require('glob'), YAML = require('js-yaml'), - _ = require('./js/lib/lodash'); + _ = require('./js/lib/lodash'), + jsonschema = require('jsonschema'), + fieldSchema = require('./data/presets/schema/field.json'), + presetSchema = require('./data/presets/schema/preset.json'); function read(f) { return JSON.parse(fs.readFileSync(f)); @@ -16,6 +19,21 @@ function rp(f) { return r('presets/' + f); } +function validate(file, instance, schema) { + var result = jsonschema.validate(instance, schema); + if (result.length) { + console.error(file + ": "); + result.forEach(function(error) { + if (error.property) { + console.error(error.property + ' ' + error.message); + } else { + console.error(error); + } + }); + process.exit(1); + } +} + var translations = { fields: {}, presets: {} @@ -25,12 +43,16 @@ var fields = {}; glob.sync(__dirname + '/data/presets/fields/*.json').forEach(function(file) { var field = read(file), id = path.basename(file, '.json'); + + validate(file, field, fieldSchema); + translations.fields[id] = {label: field.label}; if (field.strings) { for (var i in field.strings) { translations.fields[id][i] = field.strings[i]; } } + fields[id] = field; }); fs.writeFileSync('data/presets/fields.json', JSON.stringify(fields, null, 4)); @@ -39,10 +61,14 @@ var presets = {}; glob.sync(__dirname + '/data/presets/presets/**/*.json').forEach(function(file) { var preset = read(file), id = file.match(/presets\/presets\/([^.]*)\.json/)[1]; + + validate(file, preset, presetSchema); + translations.presets[id] = { name: preset.name, terms: (preset.terms || []).join(',') }; + presets[id] = preset; }); fs.writeFileSync('data/presets/presets.json', JSON.stringify(presets, null, 4)); diff --git a/data/presets/schema/field.json b/data/presets/schema/field.json new file mode 100644 index 000000000..f852288c5 --- /dev/null +++ b/data/presets/schema/field.json @@ -0,0 +1,67 @@ +{ + "title": "Field", + "description": "A reusable form element for presets", + "type": "object", + "properties": { + "key": { + "description": "Tag key whose value is to be displayed", + "type": "string" + }, + "keys": { + "description": "Tag keys whose value is to be displayed", + "type": "array", + "items": { + "type": "string" + } + }, + "type": { + "description": "Type of field", + "type": "string", + "enum": [ + "address", + "check", + "combo", + "defaultcheck", + "text", + "number", + "tel", + "email", + "url", + "radio", + "textarea" + ], + "required": true + }, + "label": { + "description": "English label for the form", + "type": "string", + "required": true + }, + "geometry": { + "type": "string" + }, + "default": { + "type": "string" + }, + "indexed": { + "type": "boolean" + }, + "options": { + "type": "array", + "items": { + "type": "string" + } + }, + "universal": { + "type": "boolean", + "default": false + }, + "icon": { + "type": "string" + }, + "strings": { + "type": "object" + } + }, + "additionalProperties": false +} \ No newline at end of file diff --git a/data/presets/schema/preset.json b/data/presets/schema/preset.json new file mode 100644 index 000000000..f2466671a --- /dev/null +++ b/data/presets/schema/preset.json @@ -0,0 +1,55 @@ +{ + "title": "Preset", + "description": "Associates an icon, form fields, and other UI with a set of OSM tags", + "type": "object", + "properties": { + "name": { + "description": "The English name for the feature", + "type": "string", + "required": true + }, + "geometry": { + "description": "Valid geometry types for the feature", + "type": "array", + "minItems": 1, + "uniqueItems": true, + "items": { + "type": "string", + "enum": ["point", "vertex", "line", "area"] + }, + "required": true + }, + "tags": { + "description": "Tags that must be present for the preset to match", + "type": "object", + "additionalProperties": { + "type": "string" + }, + "required": true + }, + "fields": { + "description": "Form fields that are displayed for the preset", + "type": "array", + "items": { + "type": "string" + } + }, + "icon": { + "description": "Name of preset icon which represents this preset", + "type": "string" + }, + "terms": { + "description": "English synonyms or related terms", + "type": "array", + "items": { + "type": "string" + } + }, + "searchable": { + "description": "Whether or not the preset will be suggested via search", + "type": "boolean", + "default": true + } + }, + "additionalProperties": false +} \ No newline at end of file diff --git a/package.json b/package.json index 33b2b4079..4cd2317a8 100644 --- a/package.json +++ b/package.json @@ -24,7 +24,8 @@ "mocha-phantomjs": "~1.1.1", "glob": "~3.1.21", "js-yaml": "~2.0.3", - "request": "~2.16.2" + "request": "~2.16.2", + "jsonschema": "~0.3.2" }, "engines": { "node": "~0.8.20" From 2bf81834497cab57c8c425c82ea89c244b254d2e Mon Sep 17 00:00:00 2001 From: John Firebaugh Date: Tue, 19 Mar 2013 15:00:51 -0700 Subject: [PATCH 03/10] Fix wheelchair preset --- data/locales.js | 1 + data/presets/fields.json | 2 +- data/presets/fields/wheelchair.json | 2 +- 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/data/locales.js b/data/locales.js index 9b5ac3b98..8e88a4e0e 100644 --- a/data/locales.js +++ b/data/locales.js @@ -1047,6 +1047,7 @@ locale.en = { } } }; + locale.zh = { "modes": { "add_area": { diff --git a/data/presets/fields.json b/data/presets/fields.json index 74175fc21..01032ec86 100644 --- a/data/presets/fields.json +++ b/data/presets/fields.json @@ -368,7 +368,7 @@ "no" ], "icon": "wheelchair", - "universal": "true", + "universal": true, "label": "Wheelchair Access" }, "wikipedia": { diff --git a/data/presets/fields/wheelchair.json b/data/presets/fields/wheelchair.json index 7003c7c17..a029dbd6b 100644 --- a/data/presets/fields/wheelchair.json +++ b/data/presets/fields/wheelchair.json @@ -7,6 +7,6 @@ "no" ], "icon": "wheelchair", - "universal": "true", + "universal": true, "label": "Wheelchair Access" } From b72c25e2df13f6b07ceaf996145e1bdf347292f8 Mon Sep 17 00:00:00 2001 From: Saman Bemel-Benrud Date: Tue, 19 Mar 2013 18:30:41 -0400 Subject: [PATCH 04/10] minor tweak. --- css/app.css | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/css/app.css b/css/app.css index 8ab94f302..a4714a592 100644 --- a/css/app.css +++ b/css/app.css @@ -283,7 +283,7 @@ ul.link-list li:last-child { div.hide, form.hide { - display:none; + display: none; } .deemphasize { @@ -1152,7 +1152,7 @@ div.combobox { } .tag-list { - margin-top: 10px; + padding-top: 20px; } .tag-row { From 0375349d0fa559c4bfdbe36ee3281c0704c244c8 Mon Sep 17 00:00:00 2001 From: Saman Bemel-Benrud Date: Tue, 19 Mar 2013 18:36:20 -0400 Subject: [PATCH 05/10] adding some mock-ups --- img/source/sprite.svg | 14 +- img/source/ui-mockups.svg | 6761 +++++++++++++++++++++++++++++++++++++ 2 files changed, 6768 insertions(+), 7 deletions(-) create mode 100644 img/source/ui-mockups.svg diff --git a/img/source/sprite.svg b/img/source/sprite.svg index d84000b2c..98d742f06 100644 --- a/img/source/sprite.svg +++ b/img/source/sprite.svg @@ -13,7 +13,7 @@ height="220" id="svg12393" version="1.1" - inkscape:version="0.48.1 r9760" + inkscape:version="0.48.2 r9819" sodipodi:docname="sprite.svg" inkscape:export-filename="/Users/saman/work_repos/iD/img/sprite.png" inkscape:export-xdpi="90" @@ -38,12 +38,12 @@ borderopacity="1.0" inkscape:pageopacity="0.0" inkscape:pageshadow="2" - inkscape:zoom="1" - inkscape:cx="-49.735643" - inkscape:cy="134.55123" + inkscape:zoom="1.4142136" + inkscape:cx="2.3449562" + inkscape:cy="33.776287" inkscape:document-units="px" inkscape:current-layer="layer12" - showgrid="true" + showgrid="false" inkscape:window-width="1280" inkscape:window-height="700" inkscape:window-x="361" @@ -53,7 +53,7 @@ fit-margin-left="0" fit-margin-right="0" fit-margin-bottom="0" - showguides="true" + showguides="false" inkscape:guide-bbox="true" inkscape:snap-bbox="true" inkscape:snap-nodes="false"> @@ -201,7 +201,7 @@ image/svg+xml - + diff --git a/img/source/ui-mockups.svg b/img/source/ui-mockups.svg new file mode 100644 index 000000000..fb2e9d180 --- /dev/null +++ b/img/source/ui-mockups.svg @@ -0,0 +1,6761 @@ + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + Add Form + + + + + + + Search + + + + Close + + + + + + + + + + + + + + + + + + + From e52c34ae2eb21b21ae0a52f0ee9fc2eaa9a8c74f Mon Sep 17 00:00:00 2001 From: John Firebaugh Date: Tue, 19 Mar 2013 15:57:39 -0700 Subject: [PATCH 06/10] Add preset for deprecated building=entrance tag --- data/locales.js | 4 ++++ data/presets.yaml | 3 +++ data/presets/presets.json | 10 ++++++++++ data/presets/presets/building/entrance.json | 10 ++++++++++ 4 files changed, 27 insertions(+) create mode 100644 data/presets/presets/building/entrance.json diff --git a/data/locales.js b/data/locales.js index 8e88a4e0e..6958b09ef 100644 --- a/data/locales.js +++ b/data/locales.js @@ -588,6 +588,10 @@ locale.en = { "name": "Building", "terms": "" }, + "building/entrance": { + "name": "Entrance", + "terms": "" + }, "entrance": { "name": "Entrance", "terms": "" diff --git a/data/presets.yaml b/data/presets.yaml index 155258ef0..e2666770f 100644 --- a/data/presets.yaml +++ b/data/presets.yaml @@ -256,6 +256,9 @@ en: building: name: Building terms: "" + building/entrance: + name: Entrance + terms: "" entrance: name: Entrance terms: "" diff --git a/data/presets/presets.json b/data/presets/presets.json index 19c987d0e..fed256cf0 100644 --- a/data/presets/presets.json +++ b/data/presets/presets.json @@ -837,6 +837,16 @@ "terms": [], "name": "Building" }, + "building/entrance": { + "geometry": [ + "vertex" + ], + "tags": { + "building": "entrance" + }, + "name": "Entrance", + "searchable": false + }, "entrance": { "geometry": [ "vertex" diff --git a/data/presets/presets/building/entrance.json b/data/presets/presets/building/entrance.json new file mode 100644 index 000000000..e4a1152b7 --- /dev/null +++ b/data/presets/presets/building/entrance.json @@ -0,0 +1,10 @@ +{ + "geometry": [ + "vertex" + ], + "tags": { + "building": "entrance" + }, + "name": "Entrance", + "searchable": false +} \ No newline at end of file From 80b6e4325fa2fc168b2b1016665630e1502e9f6e Mon Sep 17 00:00:00 2001 From: John Firebaugh Date: Tue, 19 Mar 2013 16:42:30 -0700 Subject: [PATCH 07/10] Circularize preserves direction (fixes #1082) --- js/id/actions/circularize.js | 7 ++--- test/spec/actions/circularize.js | 44 +++++++++++++++++++++++++++++--- 2 files changed, 44 insertions(+), 7 deletions(-) diff --git a/js/id/actions/circularize.js b/js/id/actions/circularize.js index 4dcfc0a21..dc936d48f 100644 --- a/js/id/actions/circularize.js +++ b/js/id/actions/circularize.js @@ -21,13 +21,14 @@ iD.actions.Circularize = function(wayId, projection, count) { radius = d3.median(points, function(p) { return iD.geo.dist(centroid, p); }), - ids = []; + ids = [], + sign = d3.geom.polygon(points).area() > 0 ? -1 : 1; for (var i = 0; i < count; i++) { var node, loc = projection.invert([ - centroid[0] + Math.cos((i / 12) * Math.PI * 2) * radius, - centroid[1] + Math.sin((i / 12) * Math.PI * 2) * radius]); + centroid[0] + Math.cos(sign * (i / 12) * Math.PI * 2) * radius, + centroid[1] + Math.sin(sign * (i / 12) * Math.PI * 2) * radius]); if (nodes.length) { var idx = closestIndex(nodes, loc); diff --git a/test/spec/actions/circularize.js b/test/spec/actions/circularize.js index 1b846c6f3..cb63f9ad6 100644 --- a/test/spec/actions/circularize.js +++ b/test/spec/actions/circularize.js @@ -26,7 +26,7 @@ describe("iD.actions.Circularize", function () { graph = iD.actions.Circularize('-', projection)(graph); - expect(graph.entity('-').nodes.slice(0, 4)).to.eql(['c', 'b', 'a', 'd']); + expect(graph.entity('-').nodes.slice(0, 4).sort()).to.eql(['a', 'b', 'c', 'd']); }); it("deletes unused nodes that are not members of other ways", function () { @@ -40,7 +40,7 @@ describe("iD.actions.Circularize", function () { graph = iD.actions.Circularize('-', projection, 3)(graph); - expect(graph.entity('d')).to.be.undefined; + expect(graph.entity('a')).to.be.undefined; }); it("reconnects unused nodes that are members of other ways", function () { @@ -51,12 +51,48 @@ describe("iD.actions.Circularize", function () { 'd': iD.Node({id: 'd', loc: [0, 2]}), 'e': iD.Node({id: 'e', loc: [1, 1]}), '-': iD.Way({id: '-', nodes: ['a', 'b', 'c', 'd', 'e', 'a']}), - '=': iD.Way({id: '=', nodes: ['d']}) + '=': iD.Way({id: '=', nodes: ['a']}) }); graph = iD.actions.Circularize('-', projection, 3)(graph); - expect(graph.entity('d')).to.be.undefined; + expect(graph.entity('a')).to.be.undefined; expect(graph.entity('=').nodes).to.eql(['c']); }); + + function area(id, graph) { + return d3.geom.polygon(_.pluck(graph.childNodes(graph.entity(id)), 'loc')).area(); + } + + it("leaves clockwise ways clockwise", function () { + var graph = iD.Graph({ + 'a': iD.Node({id: 'a', loc: [0, 0]}), + 'b': iD.Node({id: 'b', loc: [2, 0]}), + 'c': iD.Node({id: 'c', loc: [2, 2]}), + 'd': iD.Node({id: 'd', loc: [0, 2]}), + '+': iD.Way({id: '+', nodes: ['a', 'd', 'c', 'b', 'a']}) + }); + + expect(area('+', graph)).to.be.gt(0); + + graph = iD.actions.Circularize('+', projection)(graph); + + expect(area('+', graph)).to.be.gt(0); + }); + + it("leaves counter-clockwise ways counter-clockwise", function () { + var graph = iD.Graph({ + 'a': iD.Node({id: 'a', loc: [0, 0]}), + 'b': iD.Node({id: 'b', loc: [2, 0]}), + 'c': iD.Node({id: 'c', loc: [2, 2]}), + 'd': iD.Node({id: 'd', loc: [0, 2]}), + '-': iD.Way({id: '-', nodes: ['a', 'b', 'c', 'd', 'a']}) + }); + + expect(area('-', graph)).to.be.lt(0); + + graph = iD.actions.Circularize('-', projection)(graph); + + expect(area('-', graph)).to.be.lt(0); + }); }); From 17d9a37bc49417c4c081488b5f9db0aa709d38d5 Mon Sep 17 00:00:00 2001 From: John Firebaugh Date: Tue, 19 Mar 2013 19:50:38 -0700 Subject: [PATCH 08/10] Optimize road category for 3 column layout --- data/presets/categories.json | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/data/presets/categories.json b/data/presets/categories.json index bd10ddad6..8638106b2 100644 --- a/data/presets/categories.json +++ b/data/presets/categories.json @@ -3,15 +3,14 @@ "icon": "highway", "id": "Road", "members": [ + "highway/residential", "highway/motorway", "highway/trunk", "highway/primary", "highway/secondary", "highway/tertiary", "highway/unclassified", - "highway/residential", "highway/service", - "highway/track", - "highway" + "highway/track" ] }] From 19e51be71ac7048bc5b13cd0b24821dd19c3d4ff Mon Sep 17 00:00:00 2001 From: saman bb Date: Tue, 19 Mar 2013 23:09:51 -0400 Subject: [PATCH 09/10] minor style tweak --- css/app.css | 1 - img/source/ui-mockups.svg | 6883 +++---------------------------------- js/id/ui/tag_editor.js | 2 +- 3 files changed, 444 insertions(+), 6442 deletions(-) diff --git a/css/app.css b/css/app.css index a4714a592..50b48896c 100644 --- a/css/app.css +++ b/css/app.css @@ -1147,7 +1147,6 @@ div.combobox { /* tag editor */ .inspector-inner.additional-tags { - border-bottom: 1px solid #ccc; border-top: 1px solid #ccc; } diff --git a/img/source/ui-mockups.svg b/img/source/ui-mockups.svg index fb2e9d180..6553ee90d 100644 --- a/img/source/ui-mockups.svg +++ b/img/source/ui-mockups.svg @@ -14,8 +14,8 @@ height="1052.3622047" id="svg2" version="1.1" - inkscape:version="0.48.2 r9819" - sodipodi:docname="category.svg"> + inkscape:version="0.48.1 r9760" + sodipodi:docname="ui-mockups.svg"> + + + + + + + + + + + + + + + + + + + - - @@ -5730,11 +324,6 @@ ojL79mgC347JKhkLysePB2f7f/RmkiRJ/k/yX87U/26xd+pGAAAAAElFTkSuQmCC width="394" id="rect4307" style="color:#000000;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" /> - - - Add Form - - @@ -6606,109 +346,70 @@ ojL79mgC347JKhkLysePB2f7f/RmkiRJ/k/yX87U/26xd+pGAAAAAElFTkSuQmCC id="rect5007" style="color:#000000;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" /> + - - Search - - + Search for forms - Close + id="path5019" + d="m -864.64989,780.36218 c -3.0376,0 -5.5,2.46243 -5.5,5.5 0,3.03757 2.4624,5.5 5.5,5.5 1.0061,0 1.9387,-0.27827 2.75,-0.75 l 3.75,3.75 1,0 1,-1 0,-1 -3.75,-3.75 c 0.4717,-0.81134 0.75,-1.74387 0.75,-2.75 0,-3.03757 -2.4624,-5.5 -5.5,-5.5 z m -0.5,2 1,0 2,1 1,2 0,1 -1,2 -2,1 -1,0 -2,-1 -1,-2 0,-1 1,-2 2,-1 z" + style="color:#000000;fill:#343434;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:2;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" /> - - - - - - - + + + + + + + + + + + + Attribution + Address + Telephone + Website + + + + + + + Attribution + Address + Telephone + Website + + + + + + + + Close + + + + + + + + + Add Form + diff --git a/js/id/ui/tag_editor.js b/js/id/ui/tag_editor.js index 9c6ed6edc..847d99bc2 100644 --- a/js/id/ui/tag_editor.js +++ b/js/id/ui/tag_editor.js @@ -98,7 +98,7 @@ iD.ui.TagEditor = function(context, entity) { } editorwrap.append('div') - .attr('class','inspector-inner col12 fillL additional-tags') + .attr('class','inspector-inner col12 fillL2 additional-tags') .call(tagList, preset.id === 'other'); // Don't add for created entities From 7e4d005b140e8eabd31484dcc6bf2961a4e938fc Mon Sep 17 00:00:00 2001 From: saman bb Date: Tue, 19 Mar 2013 23:23:02 -0400 Subject: [PATCH 10/10] updating mockups. --- img/source/ui-mockups.svg | 63 ++++++++------------------------------- 1 file changed, 13 insertions(+), 50 deletions(-) diff --git a/img/source/ui-mockups.svg b/img/source/ui-mockups.svg index 6553ee90d..1bce1829d 100644 --- a/img/source/ui-mockups.svg +++ b/img/source/ui-mockups.svg @@ -126,11 +126,11 @@ inkscape:pageopacity="0.0" inkscape:pageshadow="2" inkscape:zoom="1" - inkscape:cx="-772.18361" - inkscape:cy="296.56744" + inkscape:cx="-555.31968" + inkscape:cy="837.80707" inkscape:document-units="px" inkscape:current-layer="layer1" - showgrid="false" + showgrid="true" inkscape:window-width="1497" inkscape:window-height="866" inkscape:window-x="0" @@ -172,13 +172,6 @@ inkscape:label="Layer 1" inkscape:groupmode="layer" id="layer1"> - - - - - Add Form +