From 448119324f4e0b8a6a9e865882d7f9c8ae793c03 Mon Sep 17 00:00:00 2001 From: SilentSpike Date: Tue, 5 Feb 2019 16:51:51 +0000 Subject: [PATCH 01/18] Add ability to comment on ImproveOSM issues --- modules/services/improveOSM.js | 15 ++++--- modules/ui/improveOSM_editor.js | 76 ++++++++++++++++++++++++--------- 2 files changed, 63 insertions(+), 28 deletions(-) diff --git a/modules/services/improveOSM.js b/modules/services/improveOSM.js index 5623a09db..6f7f47e03 100644 --- a/modules/services/improveOSM.js +++ b/modules/services/improveOSM.js @@ -360,17 +360,16 @@ export default { payload.targetIds = [ d.identifier ]; } - // Comments don't currently work, if they ever do in future - // it looks as though they require a separate post - // if (d.newComment !== undefined) { - // payload.text = d.newComment; - // } - - if (d.newStatus !== d.status) { + if (d.newStatus !== undefined) { payload.status = d.newStatus; payload.text = 'status changed'; } + // Comment take place of default text + if (d.newComment !== undefined) { + payload.text = d.newComment; + } + _erCache.inflightPost[d.id] = d3_request(url) .header('Content-Type', 'application/json') .post(JSON.stringify(payload), function(err) { @@ -378,6 +377,8 @@ export default { // Unsuccessful response status, keep issue open if (err.status !== 200) { return callback(err, d); } + // Just a comment, error still open + if (d.newStatus === undefined) { return callback(err, d); } that.removeError(d); diff --git a/modules/ui/improveOSM_editor.js b/modules/ui/improveOSM_editor.js index c1c29c1b5..b37107fe6 100644 --- a/modules/ui/improveOSM_editor.js +++ b/modules/ui/improveOSM_editor.js @@ -1,4 +1,5 @@ import { dispatch as d3_dispatch } from 'd3-dispatch'; +import { select as d3_select } from 'd3-selection'; import { t } from '../util/locale'; import { services } from '../services'; @@ -12,7 +13,7 @@ import { uiTooltipHtml } from './index'; -import { utilRebind } from '../util'; +import { utilNoAuto, utilRebind } from '../util'; export function uiImproveOsmEditor(context) { @@ -97,10 +98,45 @@ export function uiImproveOsmEditor(context) { .append('div') .attr('class', 'keepRight-save save-section cf'); + saveSectionEnter + .append('h4') + .attr('class', '.error-save-header') + .text(t('QA.keepRight.comment')); + + saveSectionEnter + .append('textarea') + .attr('class', 'new-comment-input') + .attr('placeholder', t('QA.keepRight.comment_placeholder')) + .attr('maxlength', 1000) + .property('value', function(d) { return d.newComment; }) + .call(utilNoAuto) + .on('input', changeInput) + .on('blur', changeInput); + // update saveSection = saveSectionEnter .merge(saveSection) .call(errorSaveButtons); + + function changeInput() { + var input = d3_select(this); + var val = input.property('value').trim(); + + if (val === '') { + val = undefined; + } + + // store the unsaved comment with the error itself + _error = _error.update({ newComment: val }); + + var errorService = services.improveOSM; + if (errorService) { + errorService.replaceError(_error); + } + + saveSection + .call(errorSaveButtons); + } } function errorSaveButtons(selection) { @@ -117,11 +153,10 @@ export function uiImproveOsmEditor(context) { .append('div') .attr('class', 'buttons'); - // Comments don't currently work - // buttonEnter - // .append('button') - // .attr('class', 'button comment-button action') - // .text(t('QA.keepRight.save_comment')); + buttonEnter + .append('button') + .attr('class', 'button comment-button action') + .text(t('QA.keepRight.save_comment')); buttonEnter .append('button') @@ -136,20 +171,19 @@ export function uiImproveOsmEditor(context) { buttonSection = buttonSection .merge(buttonEnter); - // Comments don't currently work - // buttonSection.select('.comment-button') - // .attr('disabled', function(d) { - // return d.newComment === undefined ? true : null; - // }) - // .on('click.comment', function(d) { - // this.blur(); // avoid keeping focus on the button - #4641 - // var errorService = services.improveOSM; - // if (errorService) { - // errorService.postUpdate(d, function(err, error) { - // dispatch.call('change', error); - // }); - // } - // }); + buttonSection.select('.comment-button') + .attr('disabled', function(d) { + return d.newComment === undefined ? true : null; + }) + .on('click.comment', function(d) { + this.blur(); // avoid keeping focus on the button - #4641 + var errorService = services.improveOSM; + if (errorService) { + errorService.postUpdate(d, function(err, error) { + dispatch.call('change', error); + }); + } + }); buttonSection.select('.close-button') .text(function(d) { @@ -192,4 +226,4 @@ export function uiImproveOsmEditor(context) { return utilRebind(improveOsmEditor, dispatch, 'on'); -} +} \ No newline at end of file From 28bb12b7aef0793b112db7ce309b54a8b2e69f17 Mon Sep 17 00:00:00 2001 From: SilentSpike Date: Tue, 5 Feb 2019 19:31:30 +0000 Subject: [PATCH 02/18] Add function to retrieve ImproveOSM comments Just need to have the UI make this call and use the data next. --- modules/services/improveOSM.js | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/modules/services/improveOSM.js b/modules/services/improveOSM.js index 6f7f47e03..b688a2f72 100644 --- a/modules/services/improveOSM.js +++ b/modules/services/improveOSM.js @@ -329,6 +329,29 @@ export default { }); }, + // Test case: + // http://missingroads.skobbler.net/missingGeoService/retrieveComments?tileX=137495&tileY=89379 + getComments: function(d, callback) { + var key = d.error_key; + var qParams = {}; + + if (key === 'ow') { + qParams = d.identifier; + } else if (key === 'mr') { + qParams.tileX = d.identifier.x; + qParams.tileY = d.identifier.y; + } else if (key === 'tr') { + qParams.targetId = d.identifier; + } + + var url = _impOsmUrls[key] + '/retrieveComments?' + utilQsString(qParams); + + d3_json(url, function(err, data) { + d.comments = data.comments; + return callback(err, d); + }); + }, + postUpdate: function(d, callback) { if (!services.osm.authenticated()) { // Username required in payload return callback({ message: 'Not Authenticated', status: -3}, d); From 2c7b689b472fdfee9f8970a4f1ae76f7dced44bf Mon Sep 17 00:00:00 2001 From: SilentSpike Date: Tue, 5 Feb 2019 19:49:57 +0000 Subject: [PATCH 03/18] Add comments display to ImproveOSM issues --- modules/services/improveOSM.js | 2 - modules/ui/improveOSM_comments.js | 92 +++++++++++++++++++++++++++++++ modules/ui/improveOSM_editor.js | 3 + modules/ui/index.js | 3 +- 4 files changed, 97 insertions(+), 3 deletions(-) create mode 100644 modules/ui/improveOSM_comments.js diff --git a/modules/services/improveOSM.js b/modules/services/improveOSM.js index b688a2f72..762ef115d 100644 --- a/modules/services/improveOSM.js +++ b/modules/services/improveOSM.js @@ -329,8 +329,6 @@ export default { }); }, - // Test case: - // http://missingroads.skobbler.net/missingGeoService/retrieveComments?tileX=137495&tileY=89379 getComments: function(d, callback) { var key = d.error_key; var qParams = {}; diff --git a/modules/ui/improveOSM_comments.js b/modules/ui/improveOSM_comments.js new file mode 100644 index 000000000..707869b46 --- /dev/null +++ b/modules/ui/improveOSM_comments.js @@ -0,0 +1,92 @@ +import { select as d3_select } from 'd3-selection'; + +import { t } from '../util/locale'; +import { svgIcon } from '../svg'; +import { services } from '../services'; +import { utilDetect } from '../util/detect'; + +export function uiImproveOsmComments() { + var _error; + + + function errorComments(selection) { + // make the div immediately so it appears above the buttons + var comments = selection.selectAll('.comments-container') + .data([0]); + + comments = comments.enter() + .append('div') + .attr('class', 'comments-container') + .merge(comments); + + // must retrieve comments from API before they can be displayed + services.improveOSM.getComments(_error, function(err, d) { + var commentEnter = comments.selectAll('.comment') + .data(_error.comments) + .enter() + .append('div') + .attr('class', 'comment'); + + commentEnter + .append('div') + .attr('class', 'comment-avatar') + .call(svgIcon('#iD-icon-avatar', 'comment-avatar-icon')); + + var mainEnter = commentEnter + .append('div') + .attr('class', 'comment-main'); + + var metadataEnter = mainEnter + .append('div') + .attr('class', 'comment-metadata'); + + metadataEnter + .append('div') + .attr('class', 'comment-author') + .each(function(d) { + var selection = d3_select(this); + var osm = services.osm; + if (osm && d.user) { + selection = selection + .append('a') + .attr('class', 'comment-author-link') + .attr('href', osm.userURL(d.username)) + .attr('tabindex', -1) + .attr('target', '_blank'); + } + selection + .text(function(d) { return d.username }); + }); + + metadataEnter + .append('div') + .attr('class', 'comment-date') + .text(function(d) { + return t('note.status.commented', { when: localeDateString(d.timestamp) }); + }); + + mainEnter + .append('div') + .attr('class', 'comment-text') + .append('p') + .text(function(d) { return d.text; }); + }); + } + + function localeDateString(s) { + if (!s) return null; + var detected = utilDetect(); + var options = { day: 'numeric', month: 'short', year: 'numeric' }; + var d = new Date(s); + if (isNaN(d.getTime())) return null; + return d.toLocaleDateString(detected.locale, options); + } + + errorComments.error = function(val) { + if (!arguments.length) return _error; + _error = val; + return errorComments; + }; + + return errorComments; +} \ No newline at end of file diff --git a/modules/ui/improveOSM_editor.js b/modules/ui/improveOSM_editor.js index b37107fe6..cd43541b7 100644 --- a/modules/ui/improveOSM_editor.js +++ b/modules/ui/improveOSM_editor.js @@ -7,6 +7,7 @@ import { modeBrowse } from '../modes'; import { svgIcon } from '../svg'; import { + uiImproveOsmComments, uiImproveOsmDetails, uiImproveOsmHeader, uiQuickLinks, @@ -19,6 +20,7 @@ import { utilNoAuto, utilRebind } from '../util'; export function uiImproveOsmEditor(context) { var dispatch = d3_dispatch('change'); var errorDetails = uiImproveOsmDetails(context); + var errorComments = uiImproveOsmComments(context); var errorHeader = uiImproveOsmHeader(context); var quickLinks = uiQuickLinks(); @@ -77,6 +79,7 @@ export function uiImproveOsmEditor(context) { .call(errorHeader.error(_error)) .call(quickLinks.choices(choices)) .call(errorDetails.error(_error)) + .call(errorComments.error(_error)) .call(improveOsmSaveSection); } diff --git a/modules/ui/index.js b/modules/ui/index.js index c1361064e..25775c454 100644 --- a/modules/ui/index.js +++ b/modules/ui/index.js @@ -28,6 +28,7 @@ export { uiFormFields } from './form_fields'; export { uiFullScreen } from './full_screen'; export { uiGeolocate } from './geolocate'; export { uiHelp } from './help'; +export { uiImproveOsmComments } from './improveOSM_comments'; export { uiImproveOsmDetails } from './improveOSM_details'; export { uiImproveOsmEditor } from './improveOSM_editor'; export { uiImproveOsmHeader } from './improveOSM_header'; @@ -72,4 +73,4 @@ export { uiUndoRedo } from './undo_redo'; export { uiVersion } from './version'; export { uiViewOnOSM } from './view_on_osm'; export { uiViewOnKeepRight } from './view_on_keepRight'; -export { uiZoom } from './zoom'; +export { uiZoom } from './zoom'; \ No newline at end of file From fa87ed75ae450a422676a7fcbc106fd6f206d4b4 Mon Sep 17 00:00:00 2001 From: SilentSpike Date: Tue, 5 Feb 2019 19:57:22 +0000 Subject: [PATCH 04/18] Display ImproveOSM comments oldest to newest --- modules/services/improveOSM.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/services/improveOSM.js b/modules/services/improveOSM.js index 762ef115d..9873e1e50 100644 --- a/modules/services/improveOSM.js +++ b/modules/services/improveOSM.js @@ -345,7 +345,7 @@ export default { var url = _impOsmUrls[key] + '/retrieveComments?' + utilQsString(qParams); d3_json(url, function(err, data) { - d.comments = data.comments; + d.comments = data.comments.reverse(); // comments served newest to oldest return callback(err, d); }); }, From f7bef29b92c1a084bd0bd292824b80fd049cf0d2 Mon Sep 17 00:00:00 2001 From: SilentSpike Date: Tue, 5 Feb 2019 20:03:55 +0000 Subject: [PATCH 05/18] Fix date conversion on ImproveOSM comments --- modules/ui/improveOSM_comments.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/ui/improveOSM_comments.js b/modules/ui/improveOSM_comments.js index 707869b46..a7b75d7cd 100644 --- a/modules/ui/improveOSM_comments.js +++ b/modules/ui/improveOSM_comments.js @@ -77,7 +77,7 @@ export function uiImproveOsmComments() { if (!s) return null; var detected = utilDetect(); var options = { day: 'numeric', month: 'short', year: 'numeric' }; - var d = new Date(s); + var d = new Date(s * 1000); // timestamp is served in seconds, date takes ms if (isNaN(d.getTime())) return null; return d.toLocaleDateString(detected.locale, options); } From 5fc87fb0a4aa2047d6dced108b10ddba7d6bec13 Mon Sep 17 00:00:00 2001 From: SilentSpike Date: Tue, 5 Feb 2019 20:19:54 +0000 Subject: [PATCH 06/18] Pacify eslint (I really need to start running npm test more often before pushing) --- modules/ui/improveOSM_comments.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/ui/improveOSM_comments.js b/modules/ui/improveOSM_comments.js index a7b75d7cd..14caa30d7 100644 --- a/modules/ui/improveOSM_comments.js +++ b/modules/ui/improveOSM_comments.js @@ -22,7 +22,7 @@ export function uiImproveOsmComments() { // must retrieve comments from API before they can be displayed services.improveOSM.getComments(_error, function(err, d) { var commentEnter = comments.selectAll('.comment') - .data(_error.comments) + .data(d.comments) .enter() .append('div') .attr('class', 'comment'); @@ -55,7 +55,7 @@ export function uiImproveOsmComments() { .attr('target', '_blank'); } selection - .text(function(d) { return d.username }); + .text(function(d) { return d.username; }); }); metadataEnter From c095600635c7da644548baf9b99138093bc57cb4 Mon Sep 17 00:00:00 2001 From: SilentSpike Date: Tue, 5 Feb 2019 20:44:04 +0000 Subject: [PATCH 07/18] Use more appropriate new comment header string --- modules/ui/improveOSM_editor.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/ui/improveOSM_editor.js b/modules/ui/improveOSM_editor.js index cd43541b7..54699067f 100644 --- a/modules/ui/improveOSM_editor.js +++ b/modules/ui/improveOSM_editor.js @@ -104,7 +104,7 @@ export function uiImproveOsmEditor(context) { saveSectionEnter .append('h4') .attr('class', '.error-save-header') - .text(t('QA.keepRight.comment')); + .text(t('note.newComment')); saveSectionEnter .append('textarea') From 78111955ddf34b617bf415d049b42b7fab8dbe0c Mon Sep 17 00:00:00 2001 From: SilentSpike Date: Tue, 5 Feb 2019 21:06:19 +0000 Subject: [PATCH 08/18] Fix user URL on ImproveOSM comments --- modules/ui/improveOSM_comments.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/ui/improveOSM_comments.js b/modules/ui/improveOSM_comments.js index 14caa30d7..490d7b5d9 100644 --- a/modules/ui/improveOSM_comments.js +++ b/modules/ui/improveOSM_comments.js @@ -46,7 +46,7 @@ export function uiImproveOsmComments() { .each(function(d) { var selection = d3_select(this); var osm = services.osm; - if (osm && d.user) { + if (osm && d.username) { selection = selection .append('a') .attr('class', 'comment-author-link') From 0346d8060f561f41c393a2f74abc47f96ce1571c Mon Sep 17 00:00:00 2001 From: SilentSpike Date: Tue, 5 Feb 2019 21:46:17 +0000 Subject: [PATCH 09/18] Retrieve ImproveOSM comments only once This additionally fixes the comment box not clearing on submission as I wasn't updating the error in the cache (to remove the newComment property). --- modules/services/improveOSM.js | 40 +++++++++++++++++++++++++++------- 1 file changed, 32 insertions(+), 8 deletions(-) diff --git a/modules/services/improveOSM.js b/modules/services/improveOSM.js index 9873e1e50..83572cefc 100644 --- a/modules/services/improveOSM.js +++ b/modules/services/improveOSM.js @@ -330,6 +330,9 @@ export default { }, getComments: function(d, callback) { + // If comments already retrieved no need to do so again + if (d.comments !== undefined) { return callback({}, d); } + var key = d.error_key; var qParams = {}; @@ -344,8 +347,14 @@ export default { var url = _impOsmUrls[key] + '/retrieveComments?' + utilQsString(qParams); + var that = this; d3_json(url, function(err, data) { - d.comments = data.comments.reverse(); // comments served newest to oldest + // comments are served newest to oldest + var comments = data.comments ? data.comments.reverse() : []; + + that.replaceError(d.update({ + comments: comments + })); return callback(err, d); }); }, @@ -398,15 +407,30 @@ export default { // Unsuccessful response status, keep issue open if (err.status !== 200) { return callback(err, d); } - // Just a comment, error still open - if (d.newStatus === undefined) { return callback(err, d); } - that.removeError(d); + // Just a comment, update error in cache + if (d.newStatus === undefined) { + var now = new Date(); + var comments = d.comments ? d.comments : []; - // No pretty identifier, so we just use coordinates - if (d.newStatus === 'SOLVED') { - var closedID = d.loc[1].toFixed(5) + '/' + d.loc[0].toFixed(5); - _erCache.closed[key + ':' + closedID] = true; + comments.push({ + username: payload.username, + text: payload.text, + timestamp: now.getTime() / 1000 + }); + + that.replaceError(d.update({ + comments: comments, + newComment: undefined + })); + } else { + that.removeError(d); + + if (d.newStatus === 'SOLVED') { + // No pretty identifier, so we just use coordinates + var closedID = d.loc[1].toFixed(5) + '/' + d.loc[0].toFixed(5); + _erCache.closed[key + ':' + closedID] = true; + } } return callback(err, d); From a566d58f81d8fa7e347921b29073c8174166a6c5 Mon Sep 17 00:00:00 2001 From: SilentSpike Date: Tue, 5 Feb 2019 21:48:06 +0000 Subject: [PATCH 10/18] Fix error on ImproveOSM issues with no comments --- modules/ui/improveOSM_comments.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/modules/ui/improveOSM_comments.js b/modules/ui/improveOSM_comments.js index 490d7b5d9..47608e0c5 100644 --- a/modules/ui/improveOSM_comments.js +++ b/modules/ui/improveOSM_comments.js @@ -21,6 +21,8 @@ export function uiImproveOsmComments() { // must retrieve comments from API before they can be displayed services.improveOSM.getComments(_error, function(err, d) { + if (!d.comments) { return; } // nothing to do here + var commentEnter = comments.selectAll('.comment') .data(d.comments) .enter() From bb0a47b2555600de7638d6b47462721840b98236 Mon Sep 17 00:00:00 2001 From: Bryan Housel Date: Thu, 7 Feb 2019 10:35:50 -0500 Subject: [PATCH 11/18] Remove `kr` and `keepRight` for styles used generically (it was weird to see these classes in improveOSM components) --- css/65_data.css | 8 ++-- css/80_app.css | 66 ++++++++++++++++---------------- modules/services/improveOSM.js | 6 +-- modules/services/keepRight.js | 6 +-- modules/ui/improveOSM_details.js | 14 +++---- modules/ui/improveOSM_editor.js | 10 ++--- modules/ui/improveOSM_header.js | 10 ++--- modules/ui/keepRight_details.js | 12 +++--- modules/ui/keepRight_editor.js | 8 ++-- modules/ui/keepRight_header.js | 10 ++--- 10 files changed, 74 insertions(+), 76 deletions(-) diff --git a/css/65_data.css b/css/65_data.css index 2b19ae553..8de9ca09c 100644 --- a/css/65_data.css +++ b/css/65_data.css @@ -1,7 +1,7 @@ /* OSM Notes and KeepRight Layers */ -.kr_error-header-icon .qa_error-fill, +.error-header-icon .qa_error-fill, .layer-keepRight .qa_error .qa_error-fill, .layer-improveOSM .qa_error .qa_error-fill { stroke: #333; @@ -44,12 +44,12 @@ /* adjustment for error icon */ -.kr_error-header-icon .preset-icon-28 { +.error-header-icon .preset-icon-28 { top: auto; left: auto; } -.kr_error-header-icon { +.error-header-icon { display: flex; align-items: center; justify-content: center; @@ -211,4 +211,4 @@ stroke: #000; stroke-width: 5px; stroke-miterlimit: 1; -} \ No newline at end of file +} diff --git a/css/80_app.css b/css/80_app.css index df759735d..4715c07d4 100644 --- a/css/80_app.css +++ b/css/80_app.css @@ -591,7 +591,7 @@ button.add-note svg.icon { .field-help-title button.close, .sidebar-component .header button.data-editor-close, .sidebar-component .header button.note-editor-close, -.sidebar-component .header button.keepRight-editor-close, +.sidebar-component .header button.error-editor-close, .entity-editor-pane .header button.preset-close, .preset-list-pane .header button.preset-choose { position: absolute; @@ -601,7 +601,7 @@ button.add-note svg.icon { [dir='rtl'] .field-help-title button.close, [dir='rtl'] .sidebar-component .header button.data-editor-close, [dir='rtl'] .sidebar-component .header button.note-editor-close, -[dir='rtl'] .sidebar-component .header button.keepRight-editor-close, +[dir='rtl'] .sidebar-component .header button.error-editor-close, [dir='rtl'] .entity-editor-pane .header button.preset-close, [dir='rtl'] .preset-list-pane .header button.preset-choose { left: 0; @@ -1175,7 +1175,7 @@ img.tag-reference-wiki-image { } .data-editor .quick-links, -.keepRight-editor .quick-links, +.error-editor .quick-links, .note-editor .quick-links { padding: 5px 0 0 0; } @@ -2488,7 +2488,7 @@ input.key-trap { /* OSM Note / KeepRight Editors ------------------------------------------------------- */ .note-header, -.kr_error-header { +.error-header { background-color: #f6f6f6; border-radius: 5px; border: 1px solid #ccc; @@ -2498,7 +2498,7 @@ input.key-trap { } .note-header-icon, -.kr_error-header-icon { +.error-header-icon { background-color: #fff; padding: 10px; flex: 0 0 62px; @@ -2509,20 +2509,20 @@ input.key-trap { border-radius: 5px 0 0 5px; } [dir='rtl'] .note-header-icon, -[dir='rtl'] .kr_error-header-icon { +[dir='rtl'] .error-header-icon { border-right: unset; border-left: 1px solid #ccc; border-radius: 0 5px 5px 0; } .note-header-icon .icon-wrap, -.kr_error-header-icon .icon-wrap { +.error-header-icon .icon-wrap { position: absolute; top: 0px; } .note-header-label, -.kr_error-header-label { +.error-header-label { background-color: #f6f6f6; padding: 0 15px; flex: 1 1 100%; @@ -2531,7 +2531,7 @@ input.key-trap { border-radius: 0 5px 5px 0; } [dir='rtl'] .note-header-label, -[dir='rtl'] .kr_error-header-label { +[dir='rtl'] .error-header-label { border-radius: 5px 0 0 5px; } @@ -2598,46 +2598,44 @@ input.key-trap { } .note-save, -.keepRight-save { +.error-save { padding-top: 20px; } -.kr_error-details, -.kr_error-comment-container { + +.error-details { padding: 10px; } - -.keepRight-save .new-comment-input, -.note-save .new-comment-input { - width: 100%; - height: 100px; - max-height: 300px; - min-height: 100px; -} - -.keepRight-save .detail-section, -.note-save .detail-section { - margin: 10px 0; -} - -.note-report { - float: right; -} - -.kr_error-details-container { +.error-details-container { background: #ececec; padding: 10px; margin-top: 20px; border-radius: 4px; border: 1px solid #ccc; } - -.kr_error-details-description { +.error-details-description { margin-bottom: 10px; } -.kr_error-details-description-text::first-letter { +.error-details-description-text::first-letter { text-transform: capitalize; } +.note-save .new-comment-input, +.error-save .new-comment-input { + width: 100%; + height: 100px; + max-height: 300px; + min-height: 100px; +} + +.note-save .detail-section, +.error-save .detail-section { + margin: 10px 0; +} + +.note-report { + float: right; +} + /* Custom Data Editor ------------------------------------------------------- */ diff --git a/modules/services/improveOSM.js b/modules/services/improveOSM.js index 83572cefc..9d3b51ab7 100644 --- a/modules/services/improveOSM.js +++ b/modules/services/improveOSM.js @@ -65,11 +65,11 @@ function updateRtree(item, replace) { } function linkErrorObject(d) { - return '' + d + ''; + return '' + d + ''; } function linkEntity(d) { - return '' + d + ''; + return '' + d + ''; } function pointAverage(points) { @@ -476,4 +476,4 @@ export default { getClosedIDs: function() { return Object.keys(_erCache.closed).sort(); } -}; \ No newline at end of file +}; diff --git a/modules/services/keepRight.js b/modules/services/keepRight.js index 0995cab27..68e34587a 100644 --- a/modules/services/keepRight.js +++ b/modules/services/keepRight.js @@ -168,11 +168,11 @@ function parseError(capture, idType) { function linkErrorObject(d) { - return '' + d + ''; + return '' + d + ''; } function linkEntity(d) { - return '' + d + ''; + return '' + d + ''; } function linkURL(d) { @@ -499,4 +499,4 @@ export default { return Object.keys(_krCache.closed).sort(); } -}; \ No newline at end of file +}; diff --git a/modules/ui/improveOSM_details.js b/modules/ui/improveOSM_details.js index 075ccd0cb..efa27ef9b 100644 --- a/modules/ui/improveOSM_details.js +++ b/modules/ui/improveOSM_details.js @@ -32,7 +32,7 @@ export function uiImproveOsmDetails(context) { function improveOsmDetails(selection) { - var details = selection.selectAll('.kr_error-details') + var details = selection.selectAll('.error-details') .data( (_error ? [_error] : []), function(d) { return d.id + '-' + (d.status || 0); } @@ -43,13 +43,13 @@ export function uiImproveOsmDetails(context) { var detailsEnter = details.enter() .append('div') - .attr('class', 'kr_error-details kr_error-details-container'); + .attr('class', 'error-details error-details-container'); // description var descriptionEnter = detailsEnter .append('div') - .attr('class', 'kr_error-details-description'); + .attr('class', 'error-details-description'); descriptionEnter .append('h4') @@ -57,14 +57,14 @@ export function uiImproveOsmDetails(context) { descriptionEnter .append('div') - .attr('class', 'kr_error-details-description-text') + .attr('class', 'error-details-description-text') .html(errorDetail); // If there are entity links in the error message.. - descriptionEnter.selectAll('.kr_error_entity_link, .kr_error_object_link') + descriptionEnter.selectAll('.error_entity_link, .error_object_link') .each(function() { var link = d3_select(this); - var isObjectLink = link.classed('kr_error_object_link'); + var isObjectLink = link.classed('error_object_link'); var entityID = isObjectLink ? (utilEntityRoot(_error.object_type) + _error.object_id) : this.textContent; @@ -124,4 +124,4 @@ export function uiImproveOsmDetails(context) { return improveOsmDetails; -} \ No newline at end of file +} diff --git a/modules/ui/improveOSM_editor.js b/modules/ui/improveOSM_editor.js index 54699067f..14405b538 100644 --- a/modules/ui/improveOSM_editor.js +++ b/modules/ui/improveOSM_editor.js @@ -50,7 +50,7 @@ export function uiImproveOsmEditor(context) { headerEnter .append('button') - .attr('class', 'fr keepRight-editor-close') + .attr('class', 'fr error-editor-close') .on('click', function() { context.enter(modeBrowse(context)); }) @@ -69,12 +69,12 @@ export function uiImproveOsmEditor(context) { .attr('class', 'body') .merge(body); - var editor = body.selectAll('.keepRight-editor') + var editor = body.selectAll('.error-editor') .data([0]); editor.enter() .append('div') - .attr('class', 'modal-section keepRight-editor') + .attr('class', 'modal-section error-editor') .merge(editor) .call(errorHeader.error(_error)) .call(quickLinks.choices(choices)) @@ -99,7 +99,7 @@ export function uiImproveOsmEditor(context) { // enter var saveSectionEnter = saveSection.enter() .append('div') - .attr('class', 'keepRight-save save-section cf'); + .attr('class', 'error-save save-section cf'); saveSectionEnter .append('h4') @@ -229,4 +229,4 @@ export function uiImproveOsmEditor(context) { return utilRebind(improveOsmEditor, dispatch, 'on'); -} \ No newline at end of file +} diff --git a/modules/ui/improveOSM_header.js b/modules/ui/improveOSM_header.js index d87b7cb3e..f9ae38327 100644 --- a/modules/ui/improveOSM_header.js +++ b/modules/ui/improveOSM_header.js @@ -22,7 +22,7 @@ export function uiImproveOsmHeader() { function improveOsmHeader(selection) { - var header = selection.selectAll('.kr_error-header') + var header = selection.selectAll('.error-header') .data( (_error ? [_error] : []), function(d) { return d.id + '-' + (d.status || 0); } @@ -33,11 +33,11 @@ export function uiImproveOsmHeader() { var headerEnter = header.enter() .append('div') - .attr('class', 'kr_error-header'); + .attr('class', 'error-header'); var iconEnter = headerEnter .append('div') - .attr('class', 'kr_error-header-icon') + .attr('class', 'error-header-icon') .classed('new', function(d) { return d.id < 0; }); var svgEnter = iconEnter @@ -81,7 +81,7 @@ export function uiImproveOsmHeader() { headerEnter .append('div') - .attr('class', 'kr_error-header-label') + .attr('class', 'error-header-label') .text(errorTitle); } @@ -94,4 +94,4 @@ export function uiImproveOsmHeader() { return improveOsmHeader; -} \ No newline at end of file +} diff --git a/modules/ui/keepRight_details.js b/modules/ui/keepRight_details.js index 12d613448..96b6536b6 100644 --- a/modules/ui/keepRight_details.js +++ b/modules/ui/keepRight_details.js @@ -37,7 +37,7 @@ export function uiKeepRightDetails(context) { function keepRightDetails(selection) { - var details = selection.selectAll('.kr_error-details') + var details = selection.selectAll('.error-details') .data( (_error ? [_error] : []), function(d) { return d.id + '-' + (d.status || 0); } @@ -48,13 +48,13 @@ export function uiKeepRightDetails(context) { var detailsEnter = details.enter() .append('div') - .attr('class', 'kr_error-details kr_error-details-container'); + .attr('class', 'error-details error-details-container'); // description var descriptionEnter = detailsEnter .append('div') - .attr('class', 'kr_error-details-description'); + .attr('class', 'error-details-description'); descriptionEnter .append('h4') @@ -62,14 +62,14 @@ export function uiKeepRightDetails(context) { descriptionEnter .append('div') - .attr('class', 'kr_error-details-description-text') + .attr('class', 'error-details-description-text') .html(errorDetail); // If there are entity links in the error message.. - descriptionEnter.selectAll('.kr_error_entity_link, .kr_error_object_link') + descriptionEnter.selectAll('.error_entity_link, .error_object_link') .each(function() { var link = d3_select(this); - var isObjectLink = link.classed('kr_error_object_link'); + var isObjectLink = link.classed('error_object_link'); var entityID = isObjectLink ? (utilEntityRoot(_error.object_type) + _error.object_id) : this.textContent; diff --git a/modules/ui/keepRight_editor.js b/modules/ui/keepRight_editor.js index ca502b1e1..c35ea4b5e 100644 --- a/modules/ui/keepRight_editor.js +++ b/modules/ui/keepRight_editor.js @@ -49,7 +49,7 @@ export function uiKeepRightEditor(context) { headerEnter .append('button') - .attr('class', 'fr keepRight-editor-close') + .attr('class', 'fr error-editor-close') .on('click', function() { context.enter(modeBrowse(context)); }) @@ -68,12 +68,12 @@ export function uiKeepRightEditor(context) { .attr('class', 'body') .merge(body); - var editor = body.selectAll('.keepRight-editor') + var editor = body.selectAll('.error-editor') .data([0]); editor.enter() .append('div') - .attr('class', 'modal-section keepRight-editor') + .attr('class', 'modal-section error-editor') .merge(editor) .call(keepRightHeader.error(_error)) .call(quickLinks.choices(choices)) @@ -108,7 +108,7 @@ export function uiKeepRightEditor(context) { // enter var saveSectionEnter = saveSection.enter() .append('div') - .attr('class', 'keepRight-save save-section cf'); + .attr('class', 'error-save save-section cf'); saveSectionEnter .append('h4') diff --git a/modules/ui/keepRight_header.js b/modules/ui/keepRight_header.js index 0e611c74f..33a958b75 100644 --- a/modules/ui/keepRight_header.js +++ b/modules/ui/keepRight_header.js @@ -28,7 +28,7 @@ export function uiKeepRightHeader() { function keepRightHeader(selection) { - var header = selection.selectAll('.kr_error-header') + var header = selection.selectAll('.error-header') .data( (_error ? [_error] : []), function(d) { return d.id + '-' + (d.status || 0); } @@ -39,11 +39,11 @@ export function uiKeepRightHeader() { var headerEnter = header.enter() .append('div') - .attr('class', 'kr_error-header'); + .attr('class', 'error-header'); var iconEnter = headerEnter .append('div') - .attr('class', 'kr_error-header-icon') + .attr('class', 'error-header-icon') .classed('new', function(d) { return d.id < 0; }); iconEnter @@ -55,7 +55,7 @@ export function uiKeepRightHeader() { headerEnter .append('div') - .attr('class', 'kr_error-header-label') + .attr('class', 'error-header-label') .text(errorTitle); } @@ -68,4 +68,4 @@ export function uiKeepRightHeader() { return keepRightHeader; -} \ No newline at end of file +} From 8ec426bd9dc86768bfdea689e57fc389eca9e84a Mon Sep 17 00:00:00 2001 From: Bryan Housel Date: Thu, 7 Feb 2019 10:36:44 -0500 Subject: [PATCH 12/18] Increase contrast between waterways and ski pistes we can do: - waterways are more on the green/teal side of blue, - pistes are more on the red/magenta side of blue --- css/45_waterways.css | 14 +++++++------- css/50_misc.css | 2 +- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/css/45_waterways.css b/css/45_waterways.css index 34d970e04..8f7ea9ba2 100644 --- a/css/45_waterways.css +++ b/css/45_waterways.css @@ -2,13 +2,13 @@ /* defaults */ .preset-icon .icon.tag-waterway.other-line { - color: #77d3de; - fill: #77d3de; + color: #7dd; + fill: #7dd; } .preset-icon .icon.iD-category-water, .preset-icon .icon.tag-type-waterway, .preset-icon .icon.tag-waterway { - color: #77d3de; + color: #7dd; fill: #fff; } @@ -38,10 +38,10 @@ path.line.fill.tag-waterway { fill: rgba(119, 211, 222, 0.3); } path.line.casing.tag-waterway { - stroke: #3d6c71; + stroke: #444; } path.line.stroke.tag-waterway { - stroke: #77d3de; + stroke: #7dd; } @@ -91,9 +91,9 @@ path.line.stroke.tag-waterway-river { /* ditch */ .preset-icon .icon.tag-waterway-ditch { - color: #8eabf3; + color: #39a; } path.line.stroke.tag-waterway-ditch { - stroke: #8eabf3; + stroke: #39a; } diff --git a/css/50_misc.css b/css/50_misc.css index fe454adab..f7ac406be 100644 --- a/css/50_misc.css +++ b/css/50_misc.css @@ -93,7 +93,7 @@ path.line.casing.tag-aerialway { /* pistes */ path.line.stroke.tag-piste { - stroke: #9ac; + stroke: #a9d; } path.line.casing.tag-piste { stroke: #444; From 3875ea565bf5571b820faf1527116da2587bfbd9 Mon Sep 17 00:00:00 2001 From: Bryan Housel Date: Thu, 7 Feb 2019 10:48:19 -0500 Subject: [PATCH 13/18] Remove `mvt` querystring parameter that we never used --- modules/util/util.js | 3 --- 1 file changed, 3 deletions(-) diff --git a/modules/util/util.js b/modules/util/util.js index babfdf6aa..c7c8cb95c 100644 --- a/modules/util/util.js +++ b/modules/util/util.js @@ -138,9 +138,6 @@ export function utilStringQs(str) { if (parts.length === 2) { obj[parts[0]] = (null === parts[1]) ? '' : decodeURIComponent(parts[1]); } - if (parts[0] === 'mvt') { - obj[parts[0]] = (parts[2] !== undefined) ? (decodeURIComponent(parts[1]) + '=' + decodeURIComponent(parts[2])) : (decodeURIComponent(parts[1])); - } return obj; }, {}); } From 492bb5b37edcd3e7523f623bf1e027d76ff53cc2 Mon Sep 17 00:00:00 2001 From: Bryan Housel Date: Thu, 7 Feb 2019 11:31:32 -0500 Subject: [PATCH 14/18] Eliminate magic scale numbers from tests, add `loadNotes` test xml --- test/spec/services/mapillary.js | 2 +- test/spec/services/openstreetcam.js | 6 +-- test/spec/services/osm.js | 62 +++++++++++++++++++---------- test/spec/services/streetside.js | 10 ++--- 4 files changed, 51 insertions(+), 29 deletions(-) diff --git a/test/spec/services/mapillary.js b/test/spec/services/mapillary.js index f1ca87dc4..8642b9b51 100644 --- a/test/spec/services/mapillary.js +++ b/test/spec/services/mapillary.js @@ -14,7 +14,7 @@ describe('iD.serviceMapillary', function() { beforeEach(function() { context = iD.coreContext().assetPath('../dist/'); context.projection - .scale(667544.214430109) // z14 + .scale(iD.geoZoomToScale(14)) .translate([-116508, 0]) // 10,0 .clipExtent([[0,0], dimensions]); diff --git a/test/spec/services/openstreetcam.js b/test/spec/services/openstreetcam.js index a3f512986..13d03b56a 100644 --- a/test/spec/services/openstreetcam.js +++ b/test/spec/services/openstreetcam.js @@ -1,6 +1,6 @@ describe('iD.serviceOpenstreetcam', function() { - var dimensions = [64, 64], - context, server, openstreetcam; + var dimensions = [64, 64]; + var context, server, openstreetcam; before(function() { iD.services.openstreetcam = iD.serviceOpenstreetcam; @@ -13,7 +13,7 @@ describe('iD.serviceOpenstreetcam', function() { beforeEach(function() { context = iD.coreContext().assetPath('../dist/'); context.projection - .scale(667544.214430109) // z14 + .scale(iD.geoZoomToScale(14)) .translate([-116508, 0]) // 10,0 .clipExtent([[0,0], dimensions]); diff --git a/test/spec/services/osm.js b/test/spec/services/osm.js index 0bc95d8f3..476ff73c3 100644 --- a/test/spec/services/osm.js +++ b/test/spec/services/osm.js @@ -596,21 +596,42 @@ describe('iD.serviceOsm', function () { }); describe('#loadNotes', function() { + var notesXML = '' + + '' + + '' + + ' 1' + + ' https://www.openstreetmap.org/api/0.6/notes/1' + + ' https://www.openstreetmap.org/api/0.6/notes/1/comment' + + ' https://www.openstreetmap.org/api/0.6/notes/1/close' + + ' 2019-01-01 00:00:00 UTC' + + ' open' + + ' ' + + ' ' + + ' 2019-01-01 00:00:00 UTC' + + ' 1' + + ' Steve' + + ' https://www.openstreetmap.org/user/Steve' + + ' opened' + + ' This is a note' + + ' <p>This is a note</p>' + + ' ' + + ' ' + + '' + + ''; + beforeEach(function() { + var dimensions = [64, 64]; context.projection - .scale(116722210.56960216) - .translate([244505613.61327893, 74865520.92230521]) - .clipExtent([[0,0], [609.34375, 826]]); + .scale(iD.geoZoomToScale(14)) + .translate([-116508, 0]) // 10,0 + .clipExtent([[0,0], dimensions]); }); it('fires loadedNotes when notes are loaded', function() { connection.on('loadedNotes', spy); - connection.loadNotes(context.projection, [64, 64], {}); + connection.loadNotes(context.projection, {}); - var url = 'http://www.openstreetmap.org/api/0.6/notes?limit=10000&closed=7&bbox=-120.05859375,34.45221847282654,-119.970703125,34.52466147177173'; - var notesXML = ''; // TODO: determine output even though this test note is closed and will be gone soon - - server.respondWith('GET', url, + server.respondWith('GET', /notes\?/, [200, { 'Content-Type': 'text/xml' }, notesXML ]); server.respond(); @@ -623,7 +644,7 @@ describe('iD.serviceOsm', function () { beforeEach(function() { var dimensions = [64, 64]; context.projection - .scale(667544.214430109) // z14 + .scale(iD.geoZoomToScale(14)) .translate([-116508, 0]) // 10,0 .clipExtent([[0,0], dimensions]); }); @@ -646,17 +667,17 @@ describe('iD.serviceOsm', function () { describe('#getNote', function() { - it('returns a note', function (done) { - var note = iD.osmNote({ id: 1, loc: [0, 0], }); - var obj = { - note: { note: { 1: note } } - }; - connection.caches(obj); - var result = connection.getNote(1); - expect(result).to.deep.equal(note); - done(); - }); + it('returns a note', function (done) { + var note = iD.osmNote({ id: 1, loc: [0, 0], }); + var obj = { + note: { note: { 1: note } } + }; + connection.caches(obj); + var result = connection.getNote(1); + expect(result).to.deep.equal(note); + done(); }); + }); describe('#removeNote', function() { it('removes a note that is new', function(done) { @@ -701,7 +722,8 @@ describe('iD.serviceOsm', function () { describe('API capabilities', function() { - var capabilitiesXML = '' + + var capabilitiesXML = '' + + '' + '' + '' + '' + diff --git a/test/spec/services/streetside.js b/test/spec/services/streetside.js index b8adb2f1c..8221718d1 100644 --- a/test/spec/services/streetside.js +++ b/test/spec/services/streetside.js @@ -1,6 +1,6 @@ describe('iD.serviceStreetside', function() { - var dimensions = [64, 64], - context, server, streetside; + var dimensions = [64, 64]; + var context, server, streetside; before(function() { iD.services.streetside = iD.serviceStreetside; @@ -13,7 +13,7 @@ describe('iD.serviceStreetside', function() { beforeEach(function() { context = iD.coreContext().assetPath('../dist/'); context.projection - .scale(667544.214430109) // z14 + .scale(iD.geoZoomToScale(14)) .translate([-116508, 0]) // 10,0 .clipExtent([[0,0], dimensions]); @@ -53,7 +53,7 @@ describe('iD.serviceStreetside', function() { // adjust projection so that only one tile is fetched // (JSONP hack will return the same data for every fetch) context.projection - .scale(10680707.430881744) // z18 + .scale(iD.geoZoomToScale(18)) .translate([-1863988.9381333336, 762.8270222954452]) // 10.002,0.002 .clipExtent([[0,0], dimensions]); @@ -84,7 +84,7 @@ describe('iD.serviceStreetside', function() { it('does not load bubbles around null island', function() { context.projection - .scale(10680707.430881744) // z18 + .scale(iD.geoZoomToScale(18)) .translate([0, 0]) .clipExtent([[0,0], dimensions]); From d2735ab40c8ba086d1816af2703dad093800b785 Mon Sep 17 00:00:00 2001 From: Bryan Housel Date: Thu, 7 Feb 2019 13:41:06 -0500 Subject: [PATCH 15/18] Fix misspelling --- modules/core/history.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/core/history.js b/modules/core/history.js index cf745c563..50bf09f11 100644 --- a/modules/core/history.js +++ b/modules/core/history.js @@ -99,7 +99,7 @@ export function coreHistory(context) { } - // determine diffrence and dispatch a change event + // determine difference and dispatch a change event function change(previous) { var difference = coreDifference(previous, history.graph()); dispatch.call('change', this, difference); From 2aa409d5a9702f3e9c0c7963a530eb6130e73ca6 Mon Sep 17 00:00:00 2001 From: Bryan Housel Date: Thu, 7 Feb 2019 13:48:29 -0500 Subject: [PATCH 16/18] Fix crash when deleting rows in raw tag editor (closes #5840) This didn't always trigger a crash, but it can. It attempted to remove the row containing the key/value input fields, however this ilne is unnecessary because the change event will trigger a redraw and d3 will handle the removing milliseconds later. --- modules/ui/raw_tag_editor.js | 1 - 1 file changed, 1 deletion(-) diff --git a/modules/ui/raw_tag_editor.js b/modules/ui/raw_tag_editor.js index 50b37de57..ccf1bde49 100644 --- a/modules/ui/raw_tag_editor.js +++ b/modules/ui/raw_tag_editor.js @@ -347,7 +347,6 @@ export function uiRawTagEditor(context) { var t = {}; t[d.key] = undefined; dispatch.call('change', this, t); - d3_select(this.parentNode).remove(); } From 02790fcc5c770d08838d852028a5dedfeff2756e Mon Sep 17 00:00:00 2001 From: Bryan Housel Date: Thu, 7 Feb 2019 15:04:16 -0500 Subject: [PATCH 17/18] Also make sure you can delete the new row in the raw tag editor (re #5840) --- modules/ui/raw_tag_editor.js | 28 ++++++++++++++++++---------- 1 file changed, 18 insertions(+), 10 deletions(-) diff --git a/modules/ui/raw_tag_editor.js b/modules/ui/raw_tag_editor.js index ccf1bde49..e4e358262 100644 --- a/modules/ui/raw_tag_editor.js +++ b/modules/ui/raw_tag_editor.js @@ -155,10 +155,10 @@ export function uiRawTagEditor(context) { .order(); items - .each(function(tag) { + .each(function(d) { var row = d3_select(this); - var key = row.select('input.key'); // propagate bound data to child - var value = row.select('input.value'); // propagate bound data to child + var key = row.select('input.key'); // propagate bound data + var value = row.select('input.value'); // propagate bound data if (_entityID && taginfo && _state !== 'hover') { bindTypeahead(key, value); @@ -167,20 +167,22 @@ export function uiRawTagEditor(context) { var isRelation = (_entityID && context.entity(_entityID).type === 'relation'); var reference; - if (isRelation && tag.key === 'type') { - reference = uiTagReference({ rtype: tag.value }, context); + if (isRelation && d.key === 'type') { + reference = uiTagReference({ rtype: d.value }, context); } else { - reference = uiTagReference({ key: tag.key, value: tag.value }, context); + reference = uiTagReference({ key: d.key, value: d.value }, context); } if (_state === 'hover') { reference.showing(false); } - row.select('.inner-wrap') + row.select('.inner-wrap') // propagate bound data .call(reference.button); row.call(reference.body); + + row.select('button.remove'); // propagate bound data }); items.selectAll('input.key') @@ -344,9 +346,15 @@ export function uiRawTagEditor(context) { function removeTag(d) { if (isReadOnly(d)) return; - var t = {}; - t[d.key] = undefined; - dispatch.call('change', this, t); + + if (d.key === '') { // removing the blank row + _showBlank = false; + content(wrap); + } else { + var t = {}; + t[d.key] = undefined; + dispatch.call('change', this, t); + } } From a363f5175fa7803c6385c1a2d8db7b27949d7628 Mon Sep 17 00:00:00 2001 From: Bryan Housel Date: Thu, 7 Feb 2019 15:56:49 -0500 Subject: [PATCH 18/18] Fix tabbing beyond last row of raw tag editor in Firefox (closes #5847) - removed the stopPropagation from the combobox keydown handler to make sure that the raw_tag_editor keydown handler will run - increased timeout from 1ms to 10ms for Firefox This is related to Firefox's newish time budgeting approach that they started using around Firefox 55. As a result, very fast timers (<4ms?) may run synchronously instead of yielding and running asynchronously https://blog.wanderview.com/blog/2017/03/13/firefox-52-settimeout-changes/ (note similar code in ui/fields/combo.js to delay focus changes and redraws 10ms after the tag changes and other events have completed) --- modules/ui/combobox.js | 1 - modules/ui/raw_tag_editor.js | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/modules/ui/combobox.js b/modules/ui/combobox.js index 93b0ae596..def5e1fed 100644 --- a/modules/ui/combobox.js +++ b/modules/ui/combobox.js @@ -177,7 +177,6 @@ export function uiCombobox(context, klass) { break; case 9: // ⇥ Tab - d3_event.stopPropagation(); accept(); break; diff --git a/modules/ui/raw_tag_editor.js b/modules/ui/raw_tag_editor.js index e4e358262..47069e159 100644 --- a/modules/ui/raw_tag_editor.js +++ b/modules/ui/raw_tag_editor.js @@ -366,7 +366,7 @@ export function uiRawTagEditor(context) { _showBlank = true; content(wrap); list.selectAll('li:last-child input.key').node().focus(); - }, 1); + }, 10); } }