From 439eed4b392e551c1e433a6fd63b811b9c8b1584 Mon Sep 17 00:00:00 2001 From: Bryan Housel Date: Fri, 11 Aug 2017 17:17:46 -0400 Subject: [PATCH] WIP: refactor uiCommit into sections, introduce uiChangesetEditor uiCommit is getting kind of big as we add more to the commit pane. I'm going to split it up and put the field rendering code into a separate module, similar to how uiEntityEditor embeds uiPresetEditor for the fields. This allows us to add a few more fields that users can set on their changesets (like hashtags, source), and even hide them under a "Add field" dropdown. --- modules/ui/changeset_editor.js | 165 +++++++++++++++++++++++++++++++++ modules/ui/commit.js | 14 ++- modules/ui/index.js | 1 + 3 files changed, 179 insertions(+), 1 deletion(-) create mode 100644 modules/ui/changeset_editor.js diff --git a/modules/ui/changeset_editor.js b/modules/ui/changeset_editor.js new file mode 100644 index 000000000..e3c6a4103 --- /dev/null +++ b/modules/ui/changeset_editor.js @@ -0,0 +1,165 @@ +import * as d3 from 'd3'; +import { d3combobox } from '../lib/d3.combobox.js'; +import { t } from '../util/locale'; +import { uiField } from './field'; +import { + utilGetSetValue, + utilNoAuto, + utilRebind +} from '../util'; + + +export function uiChangesetEditor(context) { + var dispatch = d3.dispatch('change'), + fieldsArr, + changeset, + tags; + + + function changesetEditor(selection) { + + if (!fieldsArr) { + var presets = context.presets(); + + fieldsArr = []; + +// FIXME: for testing + if (presets.field('brand')) { + fieldsArr.push( + uiField(context, presets.field('brand'), changeset) + ); + } + +// FIXME: for testing + presets.universal().forEach(function(field) { + fieldsArr.push( + uiField(context, field, changeset, { show: false }) + ); + }); + + fieldsArr.forEach(function(field) { + field + .on('change', function(t, onInput) { + dispatch.call('change', field, t, onInput); + }); + }); + } + + fieldsArr.forEach(function(field) { + field + .tags(tags); + }); + + var shown = fieldsArr.filter(function(field) { return field.isShown(); }), + notShown = fieldsArr.filter(function(field) { return !field.isShown(); }); + + + var form = selection.selectAll('.preset-form') + .data([0]); + + form = form.enter() + .append('div') + .attr('class', 'preset-form inspector-inner fillL3') + .merge(form); + + + var fields = form.selectAll('.wrap-form-field') + .data(shown, function(d) { return d.id; }); + + fields.exit() + .remove(); + + // Enter + var enter = fields.enter() + .append('div') + .attr('class', function(d) { return 'wrap-form-field wrap-form-field-' + d.id; }); + + // Update + fields = fields + .merge(enter); + + fields + .order() + .each(function(d) { + d3.select(this) + .call(d.render); + }); + + + notShown = notShown.map(function(field) { + return { + title: field.label(), + value: field.label(), + field: field + }; + }); + + + var more = selection.selectAll('.more-fields') + .data((notShown.length > 0) ? [0] : []); + + more.exit() + .remove(); + + more = more.enter() + .append('div') + .attr('class', 'more-fields') + .append('label') + .text(t('inspector.add_fields')) + .merge(more); + + + var input = more.selectAll('.value') + .data([0]); + + input.exit() + .remove(); + + input = input.enter() + .append('input') + .attr('class', 'value') + .attr('type', 'text') + .call(utilNoAuto) + .merge(input); + + input + .call(utilGetSetValue, '') + .attr('placeholder', function() { + var placeholder = []; + for (var field in notShown) { + placeholder.push(notShown[field].title); + } + return placeholder.slice(0,3).join(', ') + ((placeholder.length > 3) ? '…' : ''); + }) + .call(d3combobox() + .container(context.container()) + .data(notShown) + .minItems(1) + .on('accept', function (d) { + var field = d.field; + field.show = true; + changesetEditor(selection); + field.focus(); + }) + ); + } + + + changesetEditor.changeset = function(_) { + if (!arguments.length) return changeset; + changeset = _; + fieldsArr = null; + return changesetEditor; + }; + + + changesetEditor.tags = function(_) { + if (!arguments.length) return tags; + tags = _; + // Don't reset fieldsArr here. + return changesetEditor; + }; + + + return utilRebind(changesetEditor, dispatch, 'on'); +} diff --git a/modules/ui/commit.js b/modules/ui/commit.js index bfae8b19a..7b9b7d8a7 100644 --- a/modules/ui/commit.js +++ b/modules/ui/commit.js @@ -6,6 +6,7 @@ import { osmChangeset } from '../osm'; import { modeSelect } from '../modes'; import { svgIcon } from '../svg'; import { tooltip } from '../util/tooltip'; +import { uiChangesetEditor } from './changeset_editor'; import { uiRawTagEditor } from './raw_tag_editor'; import { utilDetect } from '../util/detect'; import { @@ -41,10 +42,13 @@ export function uiCommit(context) { changeset = new osmChangeset({ tags: tags }); } + var changesetEditor = uiChangesetEditor(context) + .on('change', changeTags); + var rawTagEditor = uiRawTagEditor(context) + .on('change', changeTags); var changes = context.history().changes(), summary = context.history().difference().summary(), - rawTagEditor = uiRawTagEditor(context).on('change', changeTags), comment = context.storage('comment') || '', commentDate = +context.storage('commentDate') || 0, currDate = Date.now(), @@ -65,6 +69,14 @@ export function uiCommit(context) { .append('div') .attr('class', 'body'); + body + .append('div') + .attr('class', 'modal-section changeset-editor') + .call(changesetEditor + .changeset(changeset) + .tags(tags) + ); + // Fields var fieldSection = body diff --git a/modules/ui/index.js b/modules/ui/index.js index 3abe1ebb2..874e0354d 100644 --- a/modules/ui/index.js +++ b/modules/ui/index.js @@ -2,6 +2,7 @@ export { uiInit } from './init'; export { uiAccount } from './account'; export { uiAttribution } from './attribution'; export { uiBackground } from './background'; +export { uiChangesetEditor } from './changeset_editor'; export { uiCmd } from './cmd'; export { uiCommit } from './commit'; export { uiConfirm } from './confirm';