mirror of
https://github.com/FoggedLens/iD.git
synced 2026-02-13 09:12:52 +00:00
Merge pull request #5867 from SilentSpike/iOSM-comments
Add comments to ImproveOSM issues
This commit is contained in:
@@ -329,6 +329,36 @@ 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 = {};
|
||||
|
||||
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);
|
||||
|
||||
var that = this;
|
||||
d3_json(url, function(err, data) {
|
||||
// comments are served newest to oldest
|
||||
var comments = data.comments ? data.comments.reverse() : [];
|
||||
|
||||
that.replaceError(d.update({
|
||||
comments: 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);
|
||||
@@ -360,17 +390,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) {
|
||||
@@ -379,12 +408,29 @@ export default {
|
||||
// Unsuccessful response status, keep issue open
|
||||
if (err.status !== 200) { 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);
|
||||
|
||||
94
modules/ui/improveOSM_comments.js
Normal file
94
modules/ui/improveOSM_comments.js
Normal file
@@ -0,0 +1,94 @@
|
||||
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) {
|
||||
if (!d.comments) { return; } // nothing to do here
|
||||
|
||||
var commentEnter = comments.selectAll('.comment')
|
||||
.data(d.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.username) {
|
||||
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 * 1000); // timestamp is served in seconds, date takes ms
|
||||
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;
|
||||
}
|
||||
@@ -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';
|
||||
@@ -6,18 +7,20 @@ import { modeBrowse } from '../modes';
|
||||
import { svgIcon } from '../svg';
|
||||
|
||||
import {
|
||||
uiImproveOsmComments,
|
||||
uiImproveOsmDetails,
|
||||
uiImproveOsmHeader,
|
||||
uiQuickLinks,
|
||||
uiTooltipHtml
|
||||
} from './index';
|
||||
|
||||
import { utilRebind } from '../util';
|
||||
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();
|
||||
|
||||
@@ -76,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);
|
||||
}
|
||||
|
||||
@@ -97,10 +101,45 @@ export function uiImproveOsmEditor(context) {
|
||||
.append('div')
|
||||
.attr('class', 'keepRight-save save-section cf');
|
||||
|
||||
saveSectionEnter
|
||||
.append('h4')
|
||||
.attr('class', '.error-save-header')
|
||||
.text(t('note.newComment'));
|
||||
|
||||
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 +156,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 +174,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 +229,4 @@ export function uiImproveOsmEditor(context) {
|
||||
|
||||
|
||||
return utilRebind(improveOsmEditor, dispatch, 'on');
|
||||
}
|
||||
}
|
||||
@@ -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';
|
||||
Reference in New Issue
Block a user