diff --git a/css/80_app.css b/css/80_app.css index dcaa8ee16..702ad24f7 100644 --- a/css/80_app.css +++ b/css/80_app.css @@ -4227,7 +4227,6 @@ li.issue-fix-item button:not(.actionable) .fix-icon { } - /* 3D Map ------------------------------------------------------- */ #map3d_container { diff --git a/data/core.yaml b/data/core.yaml index 244ebe13d..1cb99b199 100644 --- a/data/core.yaml +++ b/data/core.yaml @@ -1787,8 +1787,8 @@ en: warnings: Warnings suggestions: Suggestions rules: Rules - user_resolved_issues: Issues resolved by your edits - warnings_and_errors: Warnings and errors + open_tooltip: Detected errors, warnings, and suggestions + resolved_tooltip: Issues resolved by your edits no_issues: message: everything: Everything looks fine diff --git a/data/l10n/core.en.json b/data/l10n/core.en.json index 4a850d2d3..f0333913a 100644 --- a/data/l10n/core.en.json +++ b/data/l10n/core.en.json @@ -2183,8 +2183,8 @@ "warnings": "Warnings", "suggestions": "Suggestions", "rules": "Rules", - "user_resolved_issues": "Issues resolved by your edits", - "warnings_and_errors": "Warnings and errors", + "open_tooltip": "Detected errors, warnings, and suggestions", + "resolved_tooltip": "Issues resolved by your edits", "no_issues": { "message": { "everything": "Everything looks fine", diff --git a/modules/ui/UiValidatorStatus.js b/modules/ui/UiValidatorStatus.js index 863bb6ffb..4a447c3c0 100644 --- a/modules/ui/UiValidatorStatus.js +++ b/modules/ui/UiValidatorStatus.js @@ -131,8 +131,8 @@ export class UiValidatorStatus { }); // localize tooltips - this.IssuesTooltip.title(l10n.t('issues.warnings_and_errors')); - this.ResolvedTooltip.title(l10n.t('issues.user_resolved_issues')); + this.IssuesTooltip.title(l10n.t('issues.open_tooltip')); + this.ResolvedTooltip.title(l10n.t('issues.resolved_tooltip')); } diff --git a/modules/ui/panes/issues.js b/modules/ui/panes/issues.js index 6b136bf4f..106825f78 100644 --- a/modules/ui/panes/issues.js +++ b/modules/ui/panes/issues.js @@ -17,8 +17,9 @@ export function uiPaneIssues(context) { .sections([ uiSectionValidationOptions(context), uiSectionValidationStatus(context), - uiSectionValidationIssues(context, 'issues-errors', 'error'), - uiSectionValidationIssues(context, 'issues-warnings', 'warning'), + uiSectionValidationIssues(context, 'error'), + uiSectionValidationIssues(context, 'warning'), + uiSectionValidationIssues(context, 'suggestion'), uiSectionValidationRules(context) ]); } diff --git a/modules/ui/sections/validation_issues.js b/modules/ui/sections/validation_issues.js index 1b5aab3c4..e09add51a 100644 --- a/modules/ui/sections/validation_issues.js +++ b/modules/ui/sections/validation_issues.js @@ -12,10 +12,9 @@ const MAX_ISSUES = 1000; /** * uiSectionValidateIssues * @param `context` Global shared application context - * @param `sectionID` String 'issues-errors' or 'issues-warnings' * @param `severity` String 'error', 'warning', or 'suggestion' */ -export function uiSectionValidationIssues(context, sectionID, severity) { +export function uiSectionValidationIssues(context, severity) { const editor = context.systems.editor; const l10n = context.systems.l10n; const map = context.systems.map; @@ -24,6 +23,7 @@ export function uiSectionValidationIssues(context, sectionID, severity) { const validator = context.systems.validator; const viewport = context.viewport; + const sectionID = `issues-${severity}`; const section = uiSection(context, sectionID) .label(sectionLabel) .shouldDisplay(sectionShouldDisplay) diff --git a/modules/ui/sections/validation_options.js b/modules/ui/sections/validation_options.js index 4f8a1dbe9..a8dfa6dc3 100644 --- a/modules/ui/sections/validation_options.js +++ b/modules/ui/sections/validation_options.js @@ -1,3 +1,5 @@ +import { selection } from 'd3-selection'; + import { uiSection } from '../section.js'; @@ -5,45 +7,58 @@ export function uiSectionValidationOptions(context) { const l10n = context.systems.l10n; const storage = context.systems.storage; const validator = context.systems.validator; + let _$parent; const section = uiSection(context, 'issues-options') - .content(renderContent); - + .content(render); + + + /** + * render + * Accepts a parent selection, and renders the content under it. + * (The parent selection is required the first time, but can be inferred on subsequent renders) + * @param {d3-selection} $parent - A d3-selection to a HTMLElement that this component should render itself into + */ + function render($parent = _$parent) { + if ($parent instanceof selection) { + _$parent = $parent; + } else { + return; // no parent - called too early? + } - function renderContent(selection) { - let container = selection.selectAll('.issues-options-container') + let $wrap = $parent.selectAll('.issues-options-container') .data([0]); - container = container.enter() + $wrap = $wrap.enter() .append('div') .attr('class', 'issues-options-container') - .merge(container); + .merge($wrap); const data = [ { key: 'what', values: ['edited', 'all'] }, { key: 'where', values: ['visible', 'all'] } ]; - let options = container.selectAll('.issues-option') + let $options = $wrap.selectAll('.issues-option') .data(data, d => d.key); - let optionsEnter = options.enter() + const $$options = $options.enter() .append('div') .attr('class', d => `issues-option issues-option-${d.key}`); - optionsEnter + $$options .append('div') .attr('class', 'issues-option-title') .text(d => l10n.t(`issues.options.${d.key}.title`)); - let valuesEnter = optionsEnter.selectAll('label') + const $$labels = $$options.selectAll('label') .data(d => { return d.values.map(val => ({ value: val, key: d.key }) ); }) .enter() .append('label'); - valuesEnter + $$labels .append('input') .attr('type', 'radio') .attr('name', d => `issues-option-${d.key}`) @@ -51,11 +66,12 @@ export function uiSectionValidationOptions(context) { .property('checked', d => getOptions()[d.key] === d.value) .on('change', (d3_event, d) => updateOptionValue(d3_event, d.key, d.value)); - valuesEnter + $$labels .append('span') .text(d => l10n.t(`issues.options.${d.key}.${d.value}`)); } + function getOptions() { return { what: storage.getItem('validate-what') || 'edited', // 'all', 'edited' diff --git a/test/browser/validations/curb_nodes.js b/test/browser/validations/curb_nodes.js index 35da23846..910661bc0 100644 --- a/test/browser/validations/curb_nodes.js +++ b/test/browser/validations/curb_nodes.js @@ -67,7 +67,7 @@ describe('validationCurbNodes', () => { const issue = issues[0]; expect(issue.type).to.eql('curb_nodes'); - expect(issue.severity).to.eql('warning'); + expect(issue.severity).to.eql('suggestion'); expect(issue.entityIds).to.have.lengthOf(1); expect(issue.entityIds[0]).to.eql('w-1'); } @@ -79,13 +79,13 @@ describe('validationCurbNodes', () => { }); it('flags a crossing way and residential street if the street has no curb nodes', () => { - createWaysWithOneCrossingPoint({highway: 'footway', footway: 'crossing'}, {highway: 'residential'}); + createWaysWithOneCrossingPoint({ highway: 'footway', footway: 'crossing' }, { highway: 'residential' }); const issues = validate(); verifySingleCurbNodeIssue(issues); }); it('flags a crossing way with no curb nodes on a primary road', () => { - createWaysWithOneCrossingPoint({highway: 'footway', footway: 'crossing'}, {highway: 'primary'}); + createWaysWithOneCrossingPoint({ highway: 'footway', footway: 'crossing' }, { highway: 'primary' }); const issues = validate(); verifySingleCurbNodeIssue(issues); }); @@ -110,14 +110,14 @@ describe('validationCurbNodes', () => { }); it('flags a crossing way with a missing curb node on a secondary road', () => { - createWaysWithOneCrossingPoint({highway: 'footway', footway: 'crossing'}, {highway: 'secondary'}); + createWaysWithOneCrossingPoint({ highway: 'footway', footway: 'crossing' }, { highway: 'secondary' }); const issues = validate(); verifySingleCurbNodeIssue(issues); }); it('flags a crossing way with no curb nodes on a tertiary road', () => { - createWaysWithOneCrossingPoint({highway: 'footway', footway: 'crossing'}, {highway: 'tertiary'}); + createWaysWithOneCrossingPoint({ highway: 'footway', footway: 'crossing' }, { highway: 'tertiary' }); const issues = validate(); verifySingleCurbNodeIssue(issues); }); -}); \ No newline at end of file +});