diff --git a/css/65_data.css b/css/65_data.css index d672fccff..c68afa648 100644 --- a/css/65_data.css +++ b/css/65_data.css @@ -150,13 +150,21 @@ border-left: none; } -#new-comment-input { +.note-save { + padding: 10px; +} + +.note-save #new-comment-input { width: 100%; height: 100px; max-height: 300px; min-height: 100px; } +.note-save .detail-section { + margin: 10px 0; +} + .note-report { float: right; } diff --git a/css/80_app.css b/css/80_app.css index 7475ffd59..aeba94aea 100644 --- a/css/80_app.css +++ b/css/80_app.css @@ -607,8 +607,13 @@ button.save.has-count .count::before { margin-right: 5px; } [dir='rtl'] .icon.pre-text { - margin-left: 5px; - margin-right: 0; + margin-left: 5px; + margin-right: 0; +} + +.icon.pre-text.user-icon { + margin-left: 5px; + margin-right: 5px; } .icon.light { @@ -3841,7 +3846,6 @@ svg.mouseclick use.right { } - /* Save Mode ------------------------------------------------------- */ .mode-save a.user-info { @@ -3870,6 +3874,7 @@ svg.mouseclick use.right { color: #fff; } +.note-save .field-warning, .mode-save .field-warning { background: #ffb; border: 1px solid #ccc; @@ -3877,6 +3882,7 @@ svg.mouseclick use.right { padding: 10px; } +.note-save .field-warning:empty, .mode-save .field-warning:empty { display: none; } diff --git a/data/core.yaml b/data/core.yaml index 26e750653..b317df32a 100644 --- a/data/core.yaml +++ b/data/core.yaml @@ -275,8 +275,8 @@ en: localized_translation_language: Choose language localized_translation_name: Name zoom_in_edit: Zoom in to edit - login: login - logout: logout + login: Log In + logout: Log Out loading_auth: "Connecting to OpenStreetMap..." report_a_bug: Report a bug help_translate: Help translate @@ -630,6 +630,9 @@ en: close_comment: Close and Comment open_comment: Reopen and Comment report: Report + login: You must log in to change or comment on this note. + upload_explanation: "Your comments will be publicly visible to all OpenStreetMap users." + upload_explanation_with_user: "Your comments as {user} will be publicly visible to all OpenStreetMap users." help: title: Help key: H diff --git a/dist/locales/en.json b/dist/locales/en.json index 6b2c5c7ff..e4b2ccb4d 100644 --- a/dist/locales/en.json +++ b/dist/locales/en.json @@ -352,8 +352,8 @@ "localized_translation_name": "Name" }, "zoom_in_edit": "Zoom in to edit", - "login": "login", - "logout": "logout", + "login": "Log In", + "logout": "Log Out", "loading_auth": "Connecting to OpenStreetMap...", "report_a_bug": "Report a bug", "help_translate": "Help translate", @@ -763,7 +763,10 @@ "comment": "Comment", "close_comment": "Close and Comment", "open_comment": "Reopen and Comment", - "report": "Report" + "report": "Report", + "login": "You must log in to change or comment on this note.", + "upload_explanation": "Your comments will be publicly visible to all OpenStreetMap users.", + "upload_explanation_with_user": "Your comments as {user} will be publicly visible to all OpenStreetMap users." }, "help": { "title": "Help", diff --git a/modules/ui/commit.js b/modules/ui/commit.js index ec79e7baf..8cf633cdf 100644 --- a/modules/ui/commit.js +++ b/modules/ui/commit.js @@ -167,7 +167,7 @@ export function uiCommit(context) { userLink .append('a') - .attr('class','user-info') + .attr('class', 'user-info') .text(user.display_name) .attr('href', osm.userURL(user.display_name)) .attr('tabindex', -1) diff --git a/modules/ui/note_editor.js b/modules/ui/note_editor.js index 4a15e3adc..1d96d80f1 100644 --- a/modules/ui/note_editor.js +++ b/modules/ui/note_editor.js @@ -1,5 +1,8 @@ import { dispatch as d3_dispatch } from 'd3-dispatch'; -import { select as d3_select } from 'd3-selection'; +import { + event as d3_event, + select as d3_select +} from 'd3-selection'; import { t } from '../util/locale'; import { services } from '../services'; @@ -53,29 +56,42 @@ export function uiNoteEditor(context) { .attr('class', 'body') .merge(body); - body.selectAll('.note-editor') - .data([0]) - .enter() + var editor = body.selectAll('.note-editor') + .data([0]); + + editor = editor.enter() .append('div') .attr('class', 'modal-section note-editor') + .merge(editor) .call(noteHeader.note(_note)) .call(noteComments.note(_note)) - .call(noteSave); + .call(noteSaveSection); - selection.selectAll('.footer') - .data([0]) - .enter() + var footer = selection.selectAll('.footer') + .data([0]); + + footer = footer.enter() .append('div') .attr('class', 'footer') + .merge(footer) .call(uiViewOnOSM(context).what(_note)) .call(uiNoteReport(context).note(_note)); + + + // rerender the note editor on any auth change + var osm = services.osm; + if (osm) { + osm.on('change.note-save', function() { + selection.call(noteEditor); + }); + } } - function noteSave(selection) { + function noteSaveSection(selection) { var isSelected = (_note && _note.id === context.selectedNoteID()); - var noteSave = selection.selectAll('.note-save-section') + var noteSave = selection.selectAll('.note-save') .data((isSelected ? [_note] : []), function(d) { return d.status + d.id; }); // exit @@ -85,11 +101,11 @@ export function uiNoteEditor(context) { // enter var noteSaveEnter = noteSave.enter() .append('div') - .attr('class', 'note-save-section save-section cf'); + .attr('class', 'note-save save-section cf'); noteSaveEnter .append('h4') - .attr('class', '.note-save-header') + .attr('class', 'note-save-header') .text(t('note.newComment')); noteSaveEnter @@ -105,6 +121,7 @@ export function uiNoteEditor(context) { // update noteSave = noteSaveEnter .merge(noteSave) + .call(userDetails) .call(noteSaveButtons); @@ -126,7 +143,100 @@ export function uiNoteEditor(context) { } + function userDetails(selection) { + var detailSection = selection.selectAll('.detail-section') + .data([0]); + + detailSection = detailSection.enter() + .append('div') + .attr('class', 'detail-section') + .merge(detailSection); + + var osm = services.osm; + if (!osm) return; + + // Add warning if user is not logged in + var hasAuth = osm.authenticated(); + var authWarning = detailSection.selectAll('.auth-warning') + .data(hasAuth ? [] : [0]); + + authWarning.exit() + .transition() + .duration(200) + .style('opacity', 0) + .remove(); + + var authEnter = authWarning.enter() + .insert('div', '.tag-reference-body') + .attr('class', 'field-warning auth-warning') + .style('opacity', 0); + + authEnter + .call(svgIcon('#iD-icon-alert', 'inline')); + + authEnter + .append('span') + .text(t('note.login')); + + authEnter + .append('a') + .attr('target', '_blank') + .call(svgIcon('#iD-icon-out-link', 'inline')) + .append('span') + .text(t('login')) + .on('click.note-login', function() { + d3_event.preventDefault(); + osm.authenticate(); + }); + + authEnter + .transition() + .duration(200) + .style('opacity', 1); + + + var prose = detailSection.selectAll('.note-save-prose') + .data(hasAuth ? [0] : []); + + prose.exit() + .remove(); + + prose = prose.enter() + .append('p') + .attr('class', 'note-save-prose') + .text(t('note.upload_explanation')) + .merge(prose); + + osm.userDetails(function(err, user) { + if (err) return; + + var userLink = d3_select(document.createElement('div')); + + if (user.image_url) { + userLink + .append('img') + .attr('src', user.image_url) + .attr('class', 'icon pre-text user-icon'); + } + + userLink + .append('a') + .attr('class', 'user-info') + .text(user.display_name) + .attr('href', osm.userURL(user.display_name)) + .attr('tabindex', -1) + .attr('target', '_blank'); + + prose + .html(t('note.upload_explanation_with_user', { user: userLink.html() })); + }); + } + + function noteSaveButtons(selection) { + var osm = services.osm; + var hasAuth = osm && osm.authenticated(); + var isSelected = (_note && _note.id === context.selectedNoteID()); var buttonSection = selection.selectAll('.buttons') .data((isSelected ? [_note] : []), function(d) { return d.status + d.id; }); @@ -158,6 +268,7 @@ export function uiNoteEditor(context) { .merge(buttonEnter); buttonSection.select('.status-button') // select and propagate data + .attr('disabled', (hasAuth ? null : true)) .text(function(d) { var action = (d.status === 'open' ? 'close' : 'open'); var andComment = (d.newComment ? '_comment' : ''); @@ -176,7 +287,7 @@ export function uiNoteEditor(context) { buttonSection.select('.comment-button') // select and propagate data .attr('disabled', function(d) { - return (d.status === 'open' && d.newComment) ? null : true; + return (hasAuth && d.status === 'open' && d.newComment) ? null : true; }) .on('click.save', function(d) { this.blur(); // avoid keeping focus on the button - #4641