diff --git a/css/80_app.css b/css/80_app.css index b5b1d984c..f170eb67e 100644 --- a/css/80_app.css +++ b/css/80_app.css @@ -2419,7 +2419,7 @@ input.key-trap { .inspector-hover .form-field-input-radio label span, .inspector-hover .form-field-input-radio label.remove .icon, .inspector-hover .inspector-inner .add-row, -.inspector-hover .entity-issues .issue ul.fixes { +.inspector-hover .entity-issues .issue ul.issue-fix-list { display: none; } @@ -3017,15 +3017,15 @@ div.full-screen > button:hover { .entity-issues .issue:not(:last-of-type) { margin-bottom: 10px; } -.entity-issues .issue ul.fixes li:first-child { +ul.issue-fix-list li:first-child { border-top-style: solid; border-top-width: 2px; } -.entity-issues .issue ul.fixes li:not(:last-of-type) { +ul.issue-fix-list li:not(:last-of-type) { border-bottom-style: solid; border-bottom-width: 1px; } -.entity-issues .issue:not(.fixes-open) ul.fixes { +.issue:not(.expanded) ul.issue-fix-list { display: none; } diff --git a/data/core.yaml b/data/core.yaml index 39690e29d..23f2eed27 100644 --- a/data/core.yaml +++ b/data/core.yaml @@ -1243,10 +1243,10 @@ en: fix: add_connection_vertex: title: Connect the features - undo_redo: Connected crossing features. + annotation: Connected crossing features. connect_almost_junction: title: Connect the features - undo_redo: Connected very close features. + annotation: Connected very close features. continue_from_start: title: Continue drawing from start continue_from_end: @@ -1255,24 +1255,24 @@ en: title: Delete this feature connect_endpoints: title: Connect the ends - undo_redo: Connected the endpoints of a way. + annotation: Connected the endpoints of a way. move_tags: title: Move the tags - undo_redo: Moved tags. + annotation: Moved tags. remove_generic_name: title: Remove the name - undo_redo: Removed a generic name. + annotation: Removed a generic name. remove_tag: title: Remove the tag - undo_redo: Removed tag. + annotation: Removed tag. select_preset: title: Select a feature type tag_as_disconnected: title: Tag as disconnected - undo_redo: Tagged very close features as disconnected. + annotation: Tagged very close features as disconnected. upgrade_tags: title: Upgrade tags - undo_redo: Upgraded tags. + annotation: Upgraded tags. intro: done: done ok: OK diff --git a/dist/locales/en.json b/dist/locales/en.json index c3d6ab025..48cc5676e 100644 --- a/dist/locales/en.json +++ b/dist/locales/en.json @@ -1523,11 +1523,11 @@ "fix": { "add_connection_vertex": { "title": "Connect the features", - "undo_redo": "Connected crossing features." + "annotation": "Connected crossing features." }, "connect_almost_junction": { "title": "Connect the features", - "undo_redo": "Connected very close features." + "annotation": "Connected very close features." }, "continue_from_start": { "title": "Continue drawing from start" @@ -1540,30 +1540,30 @@ }, "connect_endpoints": { "title": "Connect the ends", - "undo_redo": "Connected the endpoints of a way." + "annotation": "Connected the endpoints of a way." }, "move_tags": { "title": "Move the tags", - "undo_redo": "Moved tags." + "annotation": "Moved tags." }, "remove_generic_name": { "title": "Remove the name", - "undo_redo": "Removed a generic name." + "annotation": "Removed a generic name." }, "remove_tag": { "title": "Remove the tag", - "undo_redo": "Removed tag." + "annotation": "Removed tag." }, "select_preset": { "title": "Select a feature type" }, "tag_as_disconnected": { "title": "Tag as disconnected", - "undo_redo": "Tagged very close features as disconnected." + "annotation": "Tagged very close features as disconnected." }, "upgrade_tags": { "title": "Upgrade tags", - "undo_redo": "Upgraded tags." + "annotation": "Upgraded tags." } } }, diff --git a/modules/ui/entity_editor.js b/modules/ui/entity_editor.js index 17c473fdd..845ad37e9 100644 --- a/modules/ui/entity_editor.js +++ b/modules/ui/entity_editor.js @@ -171,11 +171,6 @@ export function uiEntityEditor(context) { .attr('class', 'namepart') .text(function(d) { return d; }); - body.select('.entity-issues') - .call(entityIssues - .entityID(_entityID) - ); - // update quick links var choices = [{ id: 'zoom_to', @@ -193,6 +188,11 @@ export function uiEntityEditor(context) { // update editor sections + body.select('.entity-issues') + .call(entityIssues + .entityID(_entityID) + ); + body.select('.preset-editor') .call(presetEditor .preset(_activePreset) diff --git a/modules/ui/entity_issues.js b/modules/ui/entity_issues.js index 4036a2ce5..10bf871b8 100644 --- a/modules/ui/entity_issues.js +++ b/modules/ui/entity_issues.js @@ -1,5 +1,4 @@ -import { dispatch as d3_dispatch } from 'd3-dispatch'; -import { select as d3_selectAll } from 'd3-selection'; +import { select as d3_select } from 'd3-selection'; import { svgIcon } from '../svg'; import { t } from '../util/locale'; @@ -10,22 +9,31 @@ import { utilRebind, utilHighlightEntities } from '../util'; export function uiEntityIssues(context) { - var dispatch = d3_dispatch('change'); + var _selection = d3_select(null); + var _expanded = 0; var _entityID; - context.validator().on('reload.entity_issues', issuesDidReload); - - function issuesDidReload() { - var selection = d3_selectAll('.entity-issues .disclosure-wrap'); - renderContent(selection); + context.validator().on('reload.entity_issues', function() { + _selection.selectAll('.entity-issues') + .call(render); update(); + }); + + + function clamp(num, min, max) { + return Math.max(min, Math.min(num, max)); } function entityIssues(selection) { + _selection = selection; + selection - .call(uiDisclosure(context, 'entity_issues', true).content(renderContent)); + .call(uiDisclosure(context, 'entity_issues', true) + .content(render) + ); + update(); } @@ -33,16 +41,17 @@ export function uiEntityIssues(context) { function update() { var issues = context.validator().getIssuesForEntityWithID(_entityID); - d3_selectAll('.entity-issues') + _selection.selectAll('.entity-issues') .classed('hide', issues.length === 0); - d3_selectAll('.hide-toggle-entity_issues span') + _selection.selectAll('.hide-toggle-entity_issues span') .text(t('issues.list_title', { count: issues.length })); } - function renderContent(selection) { + function render(selection) { var issues = context.validator().getIssuesForEntityWithID(_entityID); + _expanded = clamp(_expanded, 0, issues.length); var items = selection.selectAll('.issue') .data(issues, function(d) { return d.id(); }); @@ -52,9 +61,9 @@ export function uiEntityIssues(context) { .remove(); // Enter - var enter = items.enter() + var itemsEnter = items.enter() .append('div') - .attr('class', function (d) { return 'issue severity-' + d.severity; }) + .attr('class', function(d) { return 'issue severity-' + d.severity; }) .on('mouseover.highlight', function(d) { var ids = d.entities.map(function(e) { return e.id; }); utilHighlightEntities(ids, true, context); @@ -62,101 +71,88 @@ export function uiEntityIssues(context) { .on('mouseout.highlight', function(d) { var ids = d.entities.map(function(e) { return e.id; }); utilHighlightEntities(ids, false, context); + }) + .on('click', function(d, i) { + _expanded = i; // expand only the clicked item + items.classed('expanded', function(d, i) { return i === _expanded; }); + + var loc = d.loc(); + if (loc) { + context.map().centerZoomEase(loc, Math.max(context.map().zoom(), 18)); + } else if (d.entities && d.entities.length > 0 && + !d.entities[0].intersects(context.map().extent(), context.graph())) { + context.map().zoomToEase(d.entities[0]); + } }); - var label = enter + var labelsEnter = itemsEnter .append('button') - .classed('label', true) + .attr('class', 'label'); + + labelsEnter .call(tooltip() .html(true) .title(function(d) { return uiTooltipHtml(d.tooltip); }) .placement('top') ); - label.each(function(d) { - var iconSuffix = d.severity === 'warning' ? 'alert' : 'error'; - d3_selectAll(this) - .append('div') - .attr('title', t('issues.' + d.severity + 's.icon_tooltip')) - .style('display', 'inline') - .call(svgIcon('#iD-icon-' + iconSuffix, 'pre-text')); - }); - - label + labelsEnter .append('span') + .attr('class', 'issue-icon') + .call(svgIcon('', 'pre-text')); + + labelsEnter .append('strong') - .text(function(d) { return d.message; }); + .attr('class', 'issue-text'); + itemsEnter + .append('ul') + .attr('class', 'issue-fix-list'); - enter.each(function(d) { - var issue = d3_selectAll(this); - - var list = issue - .selectAll('ul.fixes') - .data([0]); - - if (d.fixes && d.fixes.length > 0) { - list = list.enter() - .append('ul') - .attr('class', 'fixes') - .merge(list); - - issue.selectAll('.label') - .on('click', function() { - if (!issue.classed('fixes-open')) { - issue.classed('fixes-open', true); - var loc = d.loc(); - if (loc) { - context.map().centerZoomEase(loc, Math.max(context.map().zoom(), 18)); - } else if (d.entities && d.entities.length > 0 && - !d.entities[0].intersects(context.map().extent(), context.graph())) { - context.map().zoomToEase(d.entities[0]); - } - } else { - issue.classed('fixes-open', false); - } - }); - - var fixItems = list - .selectAll('li') - .data(d.fixes); - - fixItems.exit() - .remove(); - - fixItems.enter() - .append('li') - .append('button') - .text(function(d) {return d.title; }) - .on('click', function(d) { d.onClick(); }) - .on('mouseover.highlight', function(d) { - utilHighlightEntities(d.entityIds, true, context); - }) - .on('mouseout.highlight', function(d) { - utilHighlightEntities(d.entityIds, false, context); - }); - } - }); // Update items = items - .merge(enter); + .merge(itemsEnter) + .classed('expanded', function(d, i) { return i === _expanded; }); - // open the fixes for the first issue if no others are already open - if (selection.selectAll('.issue.fixes-open').empty()) { - selection.selectAll('.issue:first-child').classed('fixes-open', true); - } + items.select('button.label') // propagate bound data + .attr('title', function(d) { + return t('issues.' + d.severity + 's.icon_tooltip'); + }); + + items.select('.issue-icon svg use') // propagate bound data + .attr('href', function(d) { + return '#iD-icon-' + (d.severity === 'warning' ? 'alert' : 'error'); + }); + + items.select('.issue-text') // propagate bound data + .text(function(d) { return d.message; }); + + + // fixes + var fixLists = items.selectAll('.issue-fix-list'); + + fixLists.selectAll('.issue-fix-item') + .data(function(d) { return d.fixes; }) + .enter() + .append('li') + .attr('class', 'issue-fix-item') + .append('button') + .text(function(d) { return d.title; }) + .on('click', function(d) { d.onClick(); }); } entityIssues.entityID = function(val) { if (!arguments.length) return _entityID; - if (_entityID === val) return entityIssues; - _entityID = val; + if (_entityID !== val) { + _entityID = val; + _expanded = 0; + } return entityIssues; }; - return utilRebind(entityIssues, dispatch, 'on'); + return entityIssues; } diff --git a/modules/ui/issues.js b/modules/ui/issues.js index 54e4051c4..8dc18175b 100644 --- a/modules/ui/issues.js +++ b/modules/ui/issues.js @@ -130,7 +130,7 @@ export function uiIssues(context) { items = items .merge(itemsEnter); - items.select('button') // propagate bound data + items.select('button.label') // propagate bound data .attr('title', function(d) { return t('issues.' + d.severity + 's.icon_tooltip'); });