diff --git a/css/65_data.css b/css/65_data.css index 7deaba72a..a8367e1fe 100644 --- a/css/65_data.css +++ b/css/65_data.css @@ -93,6 +93,10 @@ border-radius: 5px 0 0 5px; } +.note-category { + margin: 20px 0px; +} + .comments-container { background: #ececec; padding: 1px 10px; diff --git a/data/presets.yaml b/data/presets.yaml index a5c716a72..1061a765f 100644 --- a/data/presets.yaml +++ b/data/presets.yaml @@ -304,6 +304,26 @@ en: castle_type: # castle_type=* label: Type + category: + # 'none=*, updateDetails=*, missing=*, wrongLocation=*, groundtruth=*, doesNotExist=*, discussion=*' + label: Category + options: + # discussion=yes + discussion: Needs discussing + # doesNotExist=yes + doesNotExist: Does not or never existed + # groundtruth=yes + groundtruth: Ground truth or needs local confirmation + # missing=yes + missing: Something is missing + # none=yes + none: None + # updateDetails=yes + updateDetails: Update or add details + # wrongLocation=yes + wrongLocation: Wrong location + # category field placeholder + placeholder: Unknown clothes: # clothes=* label: Clothes diff --git a/data/presets/fields.json b/data/presets/fields.json index d295ff913..e1018de87 100644 --- a/data/presets/fields.json +++ b/data/presets/fields.json @@ -49,6 +49,7 @@ "capacity": {"key": "capacity", "type": "number", "minValue": 0, "label": "Capacity", "placeholder": "50, 100, 200..."}, "cash_in": {"key": "cash_in", "type": "check", "label": "Cash In"}, "castle_type": {"key": "castle_type", "type": "combo", "label": "Type"}, + "category": {"type": "radio", "keys": ["none", "updateDetails", "missing", "wrongLocation", "groundtruth", "doesNotExist", "discussion"], "label": "Category", "placeholder": "Unknown", "strings": {"options": {"none": "None", "updateDetails": "Update or add details", "missing": "Something is missing", "wrongLocation": "Wrong location", "groundtruth": "Ground truth or needs local confirmation", "doesNotExist": "Does not or never existed", "discussion": "Needs discussing"}}}, "clothes": {"key": "clothes", "type": "semiCombo", "label": "Clothes"}, "club": {"key": "club", "type": "typeCombo", "label": "Type"}, "collection_times": {"key": "collection_times", "type": "text", "label": "Collection Times"}, diff --git a/data/presets/fields/category.json b/data/presets/fields/category.json new file mode 100644 index 000000000..1af4a78b8 --- /dev/null +++ b/data/presets/fields/category.json @@ -0,0 +1,25 @@ +{ + "type": "radio", + "keys": [ + "none", + "updateDetails", + "missing", + "wrongLocation", + "groundtruth", + "doesNotExist", + "discussion" + ], + "label": "Category", + "placeholder": "Unknown", + "strings": { + "options": { + "none": "None", + "updateDetails": "Update or add details", + "missing": "Something is missing", + "wrongLocation": "Wrong location", + "groundtruth": "Ground truth or needs local confirmation", + "doesNotExist": "Does not or never existed", + "discussion": "Needs discussing" + } + } +} diff --git a/data/taginfo.json b/data/taginfo.json index 50d522098..a22acfd27 100644 --- a/data/taginfo.json +++ b/data/taginfo.json @@ -6375,6 +6375,87 @@ {"key": "capacity", "description": "Capacity"}, {"key": "cash_in", "description": "Cash In"}, {"key": "castle_type", "description": "Type"}, + {"key": "none", "value": "none", "description": "Category"}, + {"key": "none", "value": "updateDetails", "description": "Category"}, + {"key": "none", "value": "missing", "description": "Category"}, + {"key": "none", "value": "wrongLocation", "description": "Category"}, + {"key": "none", "value": "groundtruth", "description": "Category"}, + {"key": "none", "value": "doesNotExist", "description": "Category"}, + {"key": "none", "value": "discussion", "description": "Category"}, + {"key": "updateDetails", "value": "none", "description": "Category"}, + { + "key": "updateDetails", + "value": "updateDetails", + "description": "Category" + }, + {"key": "updateDetails", "value": "missing", "description": "Category"}, + { + "key": "updateDetails", + "value": "wrongLocation", + "description": "Category" + }, + {"key": "updateDetails", "value": "groundtruth", "description": "Category"}, + { + "key": "updateDetails", + "value": "doesNotExist", + "description": "Category" + }, + {"key": "updateDetails", "value": "discussion", "description": "Category"}, + {"key": "missing", "value": "none", "description": "Category"}, + {"key": "missing", "value": "updateDetails", "description": "Category"}, + {"key": "missing", "value": "missing", "description": "Category"}, + {"key": "missing", "value": "wrongLocation", "description": "Category"}, + {"key": "missing", "value": "groundtruth", "description": "Category"}, + {"key": "missing", "value": "doesNotExist", "description": "Category"}, + {"key": "missing", "value": "discussion", "description": "Category"}, + {"key": "wrongLocation", "value": "none", "description": "Category"}, + { + "key": "wrongLocation", + "value": "updateDetails", + "description": "Category" + }, + {"key": "wrongLocation", "value": "missing", "description": "Category"}, + { + "key": "wrongLocation", + "value": "wrongLocation", + "description": "Category" + }, + {"key": "wrongLocation", "value": "groundtruth", "description": "Category"}, + { + "key": "wrongLocation", + "value": "doesNotExist", + "description": "Category" + }, + {"key": "wrongLocation", "value": "discussion", "description": "Category"}, + {"key": "groundtruth", "value": "none", "description": "Category"}, + {"key": "groundtruth", "value": "updateDetails", "description": "Category"}, + {"key": "groundtruth", "value": "missing", "description": "Category"}, + {"key": "groundtruth", "value": "wrongLocation", "description": "Category"}, + {"key": "groundtruth", "value": "groundtruth", "description": "Category"}, + {"key": "groundtruth", "value": "doesNotExist", "description": "Category"}, + {"key": "groundtruth", "value": "discussion", "description": "Category"}, + {"key": "doesNotExist", "value": "none", "description": "Category"}, + { + "key": "doesNotExist", + "value": "updateDetails", + "description": "Category" + }, + {"key": "doesNotExist", "value": "missing", "description": "Category"}, + { + "key": "doesNotExist", + "value": "wrongLocation", + "description": "Category" + }, + {"key": "doesNotExist", "value": "groundtruth", "description": "Category"}, + {"key": "doesNotExist", "value": "doesNotExist", "description": "Category"}, + {"key": "doesNotExist", "value": "discussion", "description": "Category"}, + {"key": "discussion", "value": "none", "description": "Category"}, + {"key": "discussion", "value": "updateDetails", "description": "Category"}, + {"key": "discussion", "value": "missing", "description": "Category"}, + {"key": "discussion", "value": "wrongLocation", "description": "Category"}, + {"key": "discussion", "value": "groundtruth", "description": "Category"}, + {"key": "discussion", "value": "doesNotExist", "description": "Category"}, + {"key": "discussion", "value": "discussion", "description": "Category"}, {"key": "clothes", "description": "Clothes"}, {"key": "collection_times", "description": "Collection Times"}, {"key": "comment", "description": "Changeset Comment"}, diff --git a/dist/locales/en.json b/dist/locales/en.json index 7f6489a73..49bec21b2 100644 --- a/dist/locales/en.json +++ b/dist/locales/en.json @@ -1667,6 +1667,19 @@ "castle_type": { "label": "Type" }, + "category": { + "label": "Category", + "placeholder": "Unknown", + "options": { + "none": "None", + "updateDetails": "Update or add details", + "missing": "Something is missing", + "wrongLocation": "Wrong location", + "groundtruth": "Ground truth or needs local confirmation", + "doesNotExist": "Does not or never existed", + "discussion": "Needs discussing" + } + }, "clothes": { "label": "Clothes" }, diff --git a/modules/actions/move_note.js b/modules/actions/move_note.js index e2179b15a..97d89b97a 100644 --- a/modules/actions/move_note.js +++ b/modules/actions/move_note.js @@ -9,8 +9,6 @@ export function actionMoveNote(noteID, toLoc) { var note = services.osm.getNote(noteID); note.move(geoVecInterp(note.loc, toLoc, t)); - console.log('moved: ', note.loc); - // TODO: update }; action.transitionable = true; diff --git a/modules/modes/add_note.js b/modules/modes/add_note.js index f0ab36571..685dcf3c7 100644 --- a/modules/modes/add_note.js +++ b/modules/modes/add_note.js @@ -39,7 +39,7 @@ export function modeAddNote(context) { context .selectedNoteID(note.id) - .enter(modeSelectNote(context, [note.id]).newFeature(true)); + .enter(modeSelectNote(context, note.id).newFeature(true)); } diff --git a/modules/modes/drag_note.js b/modules/modes/drag_note.js index 602fac67e..8437300c2 100644 --- a/modules/modes/drag_note.js +++ b/modules/modes/drag_note.js @@ -223,7 +223,7 @@ export function modeDragNote(context) { mode.selectedNoteID = function() { - if (!arguments.length) return _activeEntity ? [_activeEntity.id] : []; + if (!arguments.length) return _activeEntity ? _activeEntity.id : []; // no assign return mode; }; diff --git a/modules/modes/select_note.js b/modules/modes/select_note.js index 7fe0c6e7d..61fe78891 100644 --- a/modules/modes/select_note.js +++ b/modules/modes/select_note.js @@ -129,7 +129,6 @@ export function modeSelectNote(context, selectedNoteID) { context.ui().sidebar .hide(); - context.selectedNoteID(null); }; diff --git a/modules/services/osm.js b/modules/services/osm.js index 03cb6f0eb..89e0ae958 100644 --- a/modules/services/osm.js +++ b/modules/services/osm.js @@ -329,7 +329,7 @@ function parseXML(xml, callback, options) { // replace or remove note from rtree function updateRtree(item, replace) { // update (or insert) in _noteCache.rtree - // TODO: other checks needed? (e.g., if cache.data.children.length decrements ...) + // NOTE: other checks needed? (e.g., if cache.data.children.length decrements ...) // remove note _noteCache.rtree.remove(item, function isEql(a, b) { return a.data.id === b.data.id; }); @@ -875,10 +875,13 @@ export default { if (!note.loc[0] || !note.loc[1] || !note.newComment) return; // location & description required + var comment = note.newComment; + if (note.newCategory && note.newCategory !== 'None') { comment += ' #' + note.newCategory; } var path = '/api/0.6/notes?' + 'lat=' + note.loc[1] + '&lon=' + note.loc[0] + - '&' + utilQsString({ text: note.newComment }); + '&' + utilQsString({ text: comment }); + _noteCache.inflightPost[note.id] = oauth.xhr( { method: 'POST', path: path }, wrapcb(this, done, _connectionID) diff --git a/modules/ui/note_comments.js b/modules/ui/note_comments.js index ccf3d5537..87649782c 100644 --- a/modules/ui/note_comments.js +++ b/modules/ui/note_comments.js @@ -11,7 +11,7 @@ export function uiNoteComments() { function noteComments(selection) { - if (_note.isNew()) { return; } + if (_note.isNew()) return; // don't draw .comments-container var comments = selection.selectAll('.comments-container') .data([0]); diff --git a/modules/ui/note_editor.js b/modules/ui/note_editor.js index 2a50f8891..f67cd3a28 100644 --- a/modules/ui/note_editor.js +++ b/modules/ui/note_editor.js @@ -9,6 +9,9 @@ import { services } from '../services'; import { modeBrowse } from '../modes'; import { svgIcon } from '../svg'; +import { uiField } from './field'; +import { uiFormFields } from './form_fields'; + import { uiNoteComments, uiNoteHeader, @@ -26,7 +29,11 @@ export function uiNoteEditor(context) { var dispatch = d3_dispatch('change'); var noteComments = uiNoteComments(); var noteHeader = uiNoteHeader(); + + var formFields = uiFormFields(context); + var _note; + var _fieldsArr; function noteEditor(selection) { @@ -107,6 +114,40 @@ export function uiNoteEditor(context) { .append('div') .attr('class', 'note-save save-section cf'); + // if new note, show categories to pick from + if (_note.isNew()) { + var presets = context.presets(); + + // NOTE: this key isn't a age and therefore there is no documentation (yet) + _fieldsArr = [ + uiField(context, presets.field('category'), null, { show: true, revert: false }), + ]; + + _fieldsArr.forEach(function(field) { + field + .on('change', changeCategory); + }); + + noteSaveEnter + .append('div') + .attr('class', 'note-category') + .call(formFields.fieldsArr(_fieldsArr)); + } + + function changeCategory() { + // NOTE: perhaps there is a better way to get value + var val = d3_select('input[name=\'category\']:checked').property('__data__') || undefined; + + // store the unsaved category with the note itself + _note = _note.update({ newCategory: val }); + var osm = services.osm; + if (osm) { + osm.replaceNote(_note); // update note cache + } + noteSave + .call(noteSaveButtons); + } + noteSaveEnter .append('h4') .attr('class', '.note-save-header') @@ -121,8 +162,8 @@ export function uiNoteEditor(context) { .attr('maxlength', 1000) .property('value', function(d) { return d.newComment; }) .call(utilNoAuto) - .on('input', change) - .on('blur', change); + .on('input', changeInput) + .on('blur', changeInput); // update noteSave = noteSaveEnter @@ -131,7 +172,7 @@ export function uiNoteEditor(context) { .call(noteSaveButtons); - function change() { + function changeInput() { var input = d3_select(this); var val = input.property('value').trim() || undefined; diff --git a/test/spec/osm/note.js b/test/spec/osm/note.js index 4e3d24817..6dc2f99ea 100644 --- a/test/spec/osm/note.js +++ b/test/spec/osm/note.js @@ -1,3 +1,5 @@ +import { geoVecInterp } from '../geo'; + describe('iD.osmNote', function () { it('returns a note', function () { expect(iD.osmNote()).to.be.an.instanceOf(iD.osmNote); @@ -10,6 +12,40 @@ describe('iD.osmNote', function () { }); }); - // TODO: add tests for #update, or remove function + describe('#update', function() { + it('returns an updated note', function() { + + }); + }); + + describe('#isNew', function() { + it('returns true if a note is new', function() { + var note = iD.osmNote({ + id: -1, + loc: [5, 10] + }); + expect(note.isNew()).to.be.true; + }); + it('returns false if a note is not new', function() { + var note = iD.osmNote({ + id: 1, + loc: [5, 10] + }); + expect(note.isNew()).to.be.false; + }); + }); + + describe('#move', function() { + it('returns an moved note', function() { + var note = iD.osmNote({ + id: 1, + loc: [5, 10] + }); + + var moveAmount = geoVecInterp(note.loc, [10, 10], 1); + note.move(moveAmount); + expect(note.loc).to.equal([10, 10]); + }); + }); }); \ No newline at end of file