mirror of
https://github.com/FoggedLens/iD.git
synced 2026-02-13 09:12:52 +00:00
174 lines
5.8 KiB
JavaScript
174 lines
5.8 KiB
JavaScript
import { dispatch as d3_dispatch } from 'd3-dispatch';
|
|
import { select as d3_select } from 'd3-selection';
|
|
|
|
import { presetManager } from '../presets';
|
|
import { t } from '../core/localizer';
|
|
import { svgIcon } from '../svg/icon';
|
|
import { uiCombobox} from './combobox';
|
|
import { uiField } from './field';
|
|
import { uiFormFields } from './form_fields';
|
|
import { utilArrayUniqBy, utilCleanOsmString, utilRebind, utilTriggerEvent, utilUnicodeCharsCount } from '../util';
|
|
|
|
|
|
export function uiChangesetEditor(context) {
|
|
var dispatch = d3_dispatch('change');
|
|
var formFields = uiFormFields(context);
|
|
var commentCombo = uiCombobox(context, 'comment').caseSensitive(true);
|
|
var _fieldsArr;
|
|
var _tags;
|
|
var _changesetID;
|
|
|
|
|
|
function changesetEditor(selection) {
|
|
render(selection);
|
|
}
|
|
|
|
|
|
function render(selection) {
|
|
var initial = false;
|
|
|
|
if (!_fieldsArr) {
|
|
initial = true;
|
|
var presets = presetManager;
|
|
|
|
_fieldsArr = [
|
|
uiField(context, presets.field('comment'), null, { show: true, revert: false }),
|
|
uiField(context, presets.field('source'), null, { show: true, revert: false }),
|
|
uiField(context, presets.field('hashtags'), null, { show: false, revert: false }),
|
|
];
|
|
|
|
_fieldsArr.forEach(function(field) {
|
|
field
|
|
.on('change', function(t, onInput) {
|
|
dispatch.call('change', field, undefined, t, onInput);
|
|
});
|
|
});
|
|
}
|
|
|
|
_fieldsArr.forEach(function(field) {
|
|
field
|
|
.tags(_tags);
|
|
});
|
|
|
|
|
|
selection
|
|
.call(formFields.fieldsArr(_fieldsArr));
|
|
|
|
|
|
if (initial) {
|
|
var commentField = selection.select('.form-field-comment textarea');
|
|
const sourceField = _fieldsArr.find(field => field.id === 'source');
|
|
var commentNode = commentField.node();
|
|
|
|
if (commentNode) {
|
|
commentNode.focus();
|
|
commentNode.select();
|
|
}
|
|
|
|
// trigger a 'blur' event so that comment field can be cleaned
|
|
// and checked for hashtags, even if retrieved from localstorage
|
|
utilTriggerEvent(commentField, 'blur');
|
|
|
|
var osm = context.connection();
|
|
if (osm) {
|
|
osm.userChangesets(function (err, changesets) {
|
|
if (err) return;
|
|
|
|
var comments = changesets.map(function(changeset) {
|
|
var comment = changeset.tags.comment;
|
|
return comment ? { title: comment, value: comment } : null;
|
|
}).filter(Boolean);
|
|
|
|
commentField
|
|
.call(commentCombo
|
|
.data(utilArrayUniqBy(comments, 'title'))
|
|
);
|
|
|
|
// add extra dropdown options to the `source` field
|
|
// based on the values used in recent changesets.
|
|
const recentSources = changesets
|
|
.flatMap((changeset) => changeset.tags.source?.split(';'))
|
|
.filter(value => !sourceField.options.includes(value))
|
|
.filter(Boolean)
|
|
.map(title => ({ title, value: title, klass: 'raw-option' }));
|
|
|
|
sourceField.impl.setCustomOptions(utilArrayUniqBy(recentSources, 'title'));
|
|
});
|
|
}
|
|
}
|
|
|
|
// Show warning(s) if comment mentions Google or comment length exceeds 255 chars
|
|
const warnings = [];
|
|
if (_tags.comment.match(/google/i)) {
|
|
warnings.push({
|
|
id: 'contains "google"',
|
|
msg: t.append('commit.google_warning'),
|
|
link: t('commit.google_warning_link')
|
|
});
|
|
}
|
|
const maxChars = context.maxCharsForTagValue();
|
|
const strLen = utilUnicodeCharsCount(utilCleanOsmString(_tags.comment, Number.POSITIVE_INFINITY));
|
|
if (strLen > maxChars || !true) {
|
|
warnings.push({
|
|
id: 'message too long',
|
|
msg: t.append('commit.changeset_comment_length_warning', { maxChars: maxChars }),
|
|
});
|
|
}
|
|
|
|
var commentWarning = selection.select('.form-field-comment').selectAll('.comment-warning')
|
|
.data(warnings, d => d.id);
|
|
|
|
commentWarning.exit()
|
|
.transition()
|
|
.duration(200)
|
|
.style('opacity', 0)
|
|
.remove();
|
|
|
|
var commentEnter = commentWarning.enter()
|
|
.insert('div', '.comment-warning')
|
|
.attr('class', 'comment-warning field-warning')
|
|
.style('opacity', 0);
|
|
|
|
commentEnter
|
|
.call(svgIcon('#iD-icon-alert', 'inline'))
|
|
.append('span');
|
|
|
|
commentEnter
|
|
.transition()
|
|
.duration(200)
|
|
.style('opacity', 1);
|
|
|
|
commentWarning.merge(commentEnter).selectAll('div > span')
|
|
.text('')
|
|
.each(function(d) {
|
|
let selection = d3_select(this);
|
|
if (d.link) {
|
|
selection = selection.append('a')
|
|
.attr('target', '_blank')
|
|
.attr('href', d.link);
|
|
}
|
|
selection.call(d.msg);
|
|
});
|
|
}
|
|
|
|
|
|
changesetEditor.tags = function(_) {
|
|
if (!arguments.length) return _tags;
|
|
_tags = _;
|
|
// Don't reset _fieldsArr here.
|
|
return changesetEditor;
|
|
};
|
|
|
|
|
|
changesetEditor.changesetID = function(_) {
|
|
if (!arguments.length) return _changesetID;
|
|
if (_changesetID === _) return changesetEditor;
|
|
_changesetID = _;
|
|
_fieldsArr = null;
|
|
return changesetEditor;
|
|
};
|
|
|
|
|
|
return utilRebind(changesetEditor, dispatch, 'on');
|
|
}
|