From 60f7dc7c0b58e52e95cbe9a9244fb8e8f939d635 Mon Sep 17 00:00:00 2001 From: Quincy Morgan Date: Wed, 1 Apr 2020 13:08:45 -0700 Subject: [PATCH] Replace `presets` property of context with singleton Remove utilPreset --- modules/behavior/draw.js | 3 +- modules/behavior/draw_way.js | 3 +- modules/behavior/hover.js | 3 +- modules/core/context.js | 13 +- modules/modes/drag_node.js | 5 +- modules/operations/downgrade.js | 4 +- modules/operations/extract.js | 6 +- modules/operations/merge.js | 4 +- modules/presets/index.js | 155 +++++++++++++++---- modules/svg/labels.js | 8 +- modules/svg/points.js | 3 +- modules/svg/vertices.js | 3 +- modules/ui/changeset_editor.js | 3 +- modules/ui/entity_editor.js | 5 +- modules/ui/feature_list.js | 7 +- modules/ui/fields/address.js | 3 +- modules/ui/fields/input.js | 3 +- modules/ui/fields/localized.js | 9 +- modules/ui/fields/radio.js | 5 +- modules/ui/fields/restrictions.js | 3 +- modules/ui/improveOSM_details.js | 3 +- modules/ui/init.js | 4 +- modules/ui/intro/area.js | 5 +- modules/ui/intro/building.js | 7 +- modules/ui/intro/intro.js | 3 +- modules/ui/intro/line.js | 5 +- modules/ui/intro/navigation.js | 7 +- modules/ui/intro/point.js | 5 +- modules/ui/keepRight_details.js | 3 +- modules/ui/note_editor.js | 2 +- modules/ui/osmose_details.js | 3 +- modules/ui/preset_icon.js | 5 +- modules/ui/preset_list.js | 17 +- modules/ui/sections/changes.js | 3 +- modules/ui/sections/feature_type.js | 5 +- modules/ui/sections/preset_fields.js | 3 +- modules/ui/sections/raw_member_editor.js | 3 +- modules/ui/sections/raw_membership_editor.js | 5 +- modules/ui/sections/selection_list.js | 3 +- modules/ui/tools/modes.js | 7 +- modules/util/index.js | 1 - modules/util/util.js | 8 +- modules/validations/mismatched_geometry.js | 7 +- modules/validations/outdated_tags.js | 7 +- modules/validations/suspicious_name.js | 6 +- test/spec/presets/index.js | 74 +++++---- 46 files changed, 289 insertions(+), 160 deletions(-) diff --git a/modules/behavior/draw.js b/modules/behavior/draw.js index 4e0de520b..736d09f7c 100644 --- a/modules/behavior/draw.js +++ b/modules/behavior/draw.js @@ -5,6 +5,7 @@ import { select as d3_select } from 'd3-selection'; +import { presetManager } from '../presets'; import { behaviorEdit } from './edit'; import { behaviorHover } from './hover'; import { behaviorTail } from './tail'; @@ -111,7 +112,7 @@ export function behaviorDraw(context) { } function allowsVertex(d) { - return d.geometry(context.graph()) === 'vertex' || context.presets().allowsVertex(d, context.graph()); + return d.geometry(context.graph()) === 'vertex' || presetManager.allowsVertex(d, context.graph()); } // related code diff --git a/modules/behavior/draw_way.js b/modules/behavior/draw_way.js index 433a904c7..b5ea78ed9 100644 --- a/modules/behavior/draw_way.js +++ b/modules/behavior/draw_way.js @@ -5,6 +5,7 @@ import { select as d3_select } from 'd3-selection'; +import { presetManager } from '../presets'; import { t } from '../core/localizer'; import { actionAddMidpoint } from '../actions/add_midpoint'; import { actionMoveNode } from '../actions/move_node'; @@ -105,7 +106,7 @@ export function behaviorDrawWay(context, wayID, index, mode, startGraph) { function allowsVertex(d) { - return d.geometry(context.graph()) === 'vertex' || context.presets().allowsVertex(d, context.graph()); + return d.geometry(context.graph()) === 'vertex' || presetManager.allowsVertex(d, context.graph()); } diff --git a/modules/behavior/hover.js b/modules/behavior/hover.js index f15da999f..ed22900b7 100644 --- a/modules/behavior/hover.js +++ b/modules/behavior/hover.js @@ -5,6 +5,7 @@ import { select as d3_select } from 'd3-selection'; +import { presetManager } from '../presets'; import { osmEntity, osmNote, QAItem } from '../osm'; import { utilKeybinding, utilRebind } from '../util'; @@ -107,7 +108,7 @@ export function behaviorHover(context) { } function allowsVertex(d) { - return d.geometry(context.graph()) === 'vertex' || context.presets().allowsVertex(d, context.graph()); + return d.geometry(context.graph()) === 'vertex' || presetManager.allowsVertex(d, context.graph()); } function modeAllowsHover(target) { diff --git a/modules/core/context.js b/modules/core/context.js index 416607f39..970ac538d 100644 --- a/modules/core/context.js +++ b/modules/core/context.js @@ -14,7 +14,7 @@ import { coreValidator } from './validator'; import { coreUploader } from './uploader'; import { geoRawMercator } from '../geo/raw_mercator'; import { modeSelect } from '../modes/select'; -import { presetIndex } from '../presets'; +import { presetManager } from '../presets'; import { rendererBackground, rendererFeatures, rendererMap, rendererPhotos } from '../renderer'; import { services } from '../services'; import { uiInit } from '../ui/init'; @@ -300,11 +300,6 @@ export function coreContext() { context.photos = () => _photos; - /* Presets */ - let _presets; - context.presets = () => _presets; - - /* Map */ let _map; context.map = () => _map; @@ -452,8 +447,6 @@ export function coreContext() { _map = rendererMap(context); _photos = rendererPhotos(context); - _presets = presetIndex(); - _ui = uiInit(context); _connection = services.osm; @@ -466,13 +459,13 @@ export function coreContext() { const hash = utilStringQs(window.location.hash); if (hash.presets) { - _presets.addablePresetIDs(new Set(hash.presets.split(','))); + presetManager.addablePresetIDs(new Set(hash.presets.split(','))); } // kick off some async work localizer.ensureLoaded(); _background.ensureLoaded(); - _presets.ensureLoaded(); + presetManager.ensureLoaded(); Object.values(services).forEach(service => { if (service && typeof service.init === 'function') { diff --git a/modules/modes/drag_node.js b/modules/modes/drag_node.js index 7f1a11e5f..a2db69a21 100644 --- a/modules/modes/drag_node.js +++ b/modules/modes/drag_node.js @@ -3,6 +3,7 @@ import { select as d3_select } from 'd3-selection'; +import { presetManager } from '../presets'; import { t } from '../core/localizer'; import { actionAddMidpoint } from '../actions/add_midpoint'; @@ -92,7 +93,7 @@ export function modeDragNode(context) { function shouldSnapToNode(target) { if (!_activeEntity) return false; return _activeEntity.geometry(context.graph()) !== 'vertex' || - (target.geometry(context.graph()) === 'vertex' || context.presets().allowsVertex(target, context.graph())); + (target.geometry(context.graph()) === 'vertex' || presetManager.allowsVertex(target, context.graph())); } @@ -237,7 +238,7 @@ export function modeDragNode(context) { context.ui().flash .duration(4000) .text(t('operations.connect.' + isInvalid, - { relation: context.presets().item('type/restriction').name() } + { relation: presetManager.item('type/restriction').name() } ))(); } } else if (isInvalid) { diff --git a/modules/operations/downgrade.js b/modules/operations/downgrade.js index 846484f26..2b76a0f2b 100644 --- a/modules/operations/downgrade.js +++ b/modules/operations/downgrade.js @@ -3,7 +3,7 @@ import { behaviorOperation } from '../behavior/operation'; import { modeSelect } from '../modes/select'; import { t } from '../core/localizer'; import { uiCmd } from '../ui/cmd'; - +import { presetManager } from '../presets'; export function operationDowngrade(selectedIDs, context) { var affectedFeatureCount = 0; @@ -31,7 +31,7 @@ export function operationDowngrade(selectedIDs, context) { function downgradeTypeForEntityID(entityID) { var graph = context.graph(); var entity = graph.entity(entityID); - var preset = context.presets().match(entity, graph); + var preset = presetManager.match(entity, graph); if (!preset || preset.isFallback()) return null; diff --git a/modules/operations/extract.js b/modules/operations/extract.js index 3f33b9996..003993dd7 100644 --- a/modules/operations/extract.js +++ b/modules/operations/extract.js @@ -3,7 +3,7 @@ import { actionMoveNode } from '../actions/move_node'; import { behaviorOperation } from '../behavior/operation'; import { modeMove } from '../modes/move'; import { t } from '../core/localizer'; - +import { presetManager } from '../presets'; export function operationExtract(selectedIDs, context) { var entityID = selectedIDs.length && selectedIDs[0]; @@ -52,7 +52,7 @@ export function operationExtract(selectedIDs, context) { if (!entity.hasInterestingTags()) return false; if (geometry === 'area') { - var preset = context.presets().match(entity, graph); + var preset = presetManager.match(entity, graph); return preset.geometry.indexOf('point') !== -1; } @@ -78,7 +78,7 @@ export function operationExtract(selectedIDs, context) { var disableReason = operation.disabled(); if (disableReason) { return t('operations.extract.' + disableReason + '.' + geometry + '.single', - { relation: context.presets().item('type/restriction').name() }); + { relation: presetManager.item('type/restriction').name() }); } else { return t('operations.extract.description.' + geometry + '.single'); } diff --git a/modules/operations/merge.js b/modules/operations/merge.js index b8d436fc2..da442715b 100644 --- a/modules/operations/merge.js +++ b/modules/operations/merge.js @@ -7,7 +7,7 @@ import { actionMergePolygon } from '../actions/merge_polygon'; import { behaviorOperation } from '../behavior/operation'; import { modeSelect } from '../modes/select'; - +import { presetManager } from '../presets'; export function operationMerge(selectedIDs, context) { @@ -67,7 +67,7 @@ export function operationMerge(selectedIDs, context) { if (j && m && p && n) { if (j === 'restriction' || n === 'restriction') { return t('operations.merge.restriction', - { relation: context.presets().item('type/restriction').name() }); + { relation: presetManager.item('type/restriction').name() }); } else if (p === 'incomplete_relation') { return t('operations.merge.incomplete_relation'); diff --git a/modules/presets/index.js b/modules/presets/index.js index e72516643..ad4da51ce 100644 --- a/modules/presets/index.js +++ b/modules/presets/index.js @@ -14,13 +14,15 @@ export { presetCollection }; export { presetField }; export { presetPreset }; +let _mainPresetIndex = presetIndex(); // singleton +export { _mainPresetIndex as presetManager }; // // `presetIndex` wraps a `presetCollection` // with methods for loading new data and returning defaults // export function presetIndex() { - const dispatch = d3_dispatch('recentsChange'); + const dispatch = d3_dispatch('favoritePreset', 'recentsChange'); const MAXRECENTS = 30; // seed the preset lists with geometry fallbacks @@ -45,6 +47,7 @@ export function presetIndex() { let _universal = []; let _addablePresetIDs = null; // Set of preset IDs that the user can add let _recents; + let _favorites; // Index of presets by (geometry, tag key). let _geometryIndex = { point: {}, vertex: {}, line: {}, area: {}, relation: {} }; @@ -322,7 +325,7 @@ export function presetIndex() { }; // pass a Set of addable preset ids - _this.addablePresetIDs = function(val) { + _this.addablePresetIDs = (val) => { if (!arguments.length) return _addablePresetIDs; _addablePresetIDs = val; @@ -343,39 +346,47 @@ export function presetIndex() { }; - function RibbonItem(preset, geometry, source) { + function RibbonItem(preset, source) { let item = {}; item.preset = preset; - item.geometry = geometry; item.source = source; + item.isFavorite = () => item.source === 'favorite'; item.isRecent = () => item.source === 'recent'; - item.matches = (preset, geometry) => item.preset.id === preset.id && item.geometry === geometry; - item.minified = () => ({ pID: item.preset.id, geom: item.geometry }); + item.matches = (preset) => item.preset.id === preset.id; + item.minified = () => ({ pID: item.preset.id }); return item; } function ribbonItemForMinified(d, source) { - if (d && d.pID && d.geom) { + if (d && d.pID) { const preset = _this.item(d.pID); if (!preset) return null; - - let geom = d.geom; - // treat point and vertex features as one geometry - if (geom === 'vertex') geom = 'point'; - - // iD's presets could have changed since this was saved, - // so make sure it's still valid. - if (preset.matchGeometry(geom) || (geom === 'point' && preset.matchGeometry('vertex'))) { - return RibbonItem(preset, geom, source); - } + return RibbonItem(preset, source); } return null; } + _this.getGenericRibbonItems = () => { + return ['point', 'line', 'area'].map(id => RibbonItem(_this.item(id), 'generic')); + }; + + + _this.getAddable = () => { + if (!_addablePresetIDs) return []; + + return _addablePresetIDs.map((id) => { + const preset = _this.item(id); + if (preset) { + return RibbonItem(preset, 'addable'); + } + }).filter(Boolean); + }; + + function setRecents(items) { _recents = items; const minifiedItems = items.map(d => d.minified()); @@ -398,8 +409,21 @@ export function presetIndex() { }; - _this.removeRecent = (preset, geometry) => { - const item = _this.recentMatching(preset, geometry); + _this.addRecent = (preset, besidePreset, after) => { + const recents = _this.getRecents(); + + const beforeItem = _this.recentMatching(besidePreset); + let toIndex = recents.indexOf(beforeItem); + if (after) toIndex += 1; + + const newItem = RibbonItem(preset, 'recent'); + recents.splice(toIndex, 0, newItem); + setRecents(recents); + }; + + + _this.removeRecent = (preset) => { + const item = _this.recentMatching(preset); if (item) { let items = _this.getRecents(); items.splice(items.indexOf(item), 1); @@ -408,11 +432,10 @@ export function presetIndex() { }; - _this.recentMatching = (preset, geometry) => { - geometry = _this.fallback(geometry).id; + _this.recentMatching = (preset) => { const items = _this.getRecents(); for (let i in items) { - if (items[i].matches(preset, geometry)) { + if (items[i].matches(preset)) { return items[i]; } } @@ -440,17 +463,15 @@ export function presetIndex() { }; - _this.setMostRecent = (preset, geometry) => { + _this.setMostRecent = (preset) => { if (preset.searchable === false) return; - geometry = _this.fallback(geometry).id; - let items = _this.getRecents(); - let item = _this.recentMatching(preset, geometry); + let item = _this.recentMatching(preset); if (item) { items.splice(items.indexOf(item), 1); } else { - item = RibbonItem(preset, geometry, 'recent'); + item = RibbonItem(preset, 'recent'); } // remove the last recent (first in, first out) @@ -463,6 +484,86 @@ export function presetIndex() { setRecents(items); }; + function setFavorites(items) { + _favorites = items; + const minifiedItems = items.map(d => d.minified()); + prefs('preset_favorites', JSON.stringify(minifiedItems)); + + // call update + dispatch.call('favoritePreset'); + } + + _this.addFavorite = (preset, besidePreset, after) => { + const favorites = _this.getFavorites(); + + const beforeItem = _this.favoriteMatching(besidePreset); + let toIndex = favorites.indexOf(beforeItem); + if (after) toIndex += 1; + + const newItem = RibbonItem(preset, 'favorite'); + favorites.splice(toIndex, 0, newItem); + setFavorites(favorites); + }; + + _this.toggleFavorite = (preset) => { + const favs = _this.getFavorites(); + const favorite = _this.favoriteMatching(preset); + if (favorite) { + favs.splice(favs.indexOf(favorite), 1); + } else { + // only allow 10 favorites + if (favs.length === 10) { + // remove the last favorite (last in, first out) + favs.pop(); + } + // append array + favs.push(RibbonItem(preset, 'favorite')); + } + setFavorites(favs); + }; + + + _this.removeFavorite = (preset) => { + const item = _this.favoriteMatching(preset); + if (item) { + const items = _this.getFavorites(); + items.splice(items.indexOf(item), 1); + setFavorites(items); + } + }; + + + _this.getFavorites = () => { + if (!_favorites) { + + // fetch from local storage + let rawFavorites = JSON.parse(prefs('preset_favorites')); + + if (!rawFavorites) { + rawFavorites = []; + prefs('preset_favorites', JSON.stringify(rawFavorites)); + } + + _favorites = rawFavorites.reduce((output, d) => { + const item = ribbonItemForMinified(d, 'favorite'); + if (item && item.preset.addable()) output.push(item); + return output; + }, []); + } + return _favorites; + }; + + + _this.favoriteMatching = (preset) => { + const favs = _this.getFavorites(); + for (let index in favs) { + if (favs[index].matches(preset)) { + return favs[index]; + } + } + return null; + }; + return utilRebind(_this, dispatch, 'on'); } diff --git a/modules/svg/labels.js b/modules/svg/labels.js index 6165957d9..117c4867f 100644 --- a/modules/svg/labels.js +++ b/modules/svg/labels.js @@ -8,7 +8,7 @@ import { geoExtent, geoPolygonIntersectsPolygon, geoPathLength, geoScaleToZoom, geoVecInterp, geoVecLength } from '../geo'; - +import { presetManager } from '../presets'; import { osmEntity } from '../osm'; import { utilDetect } from '../util/detect'; import { utilDisplayName, utilDisplayNameForPath, utilEntitySelector } from '../util'; @@ -200,7 +200,7 @@ export function svgLabels(projection, context) { .merge(icons) .attr('transform', get(labels, 'transform')) .attr('xlink:href', function(d) { - var preset = context.presets().match(d, context.graph()); + var preset = presetManager.match(d, context.graph()); var picon = preset && preset.icon; if (!picon) { @@ -312,7 +312,7 @@ export function svgLabels(projection, context) { } // Determine which entities are label-able - var preset = geometry === 'area' && context.presets().match(entity, graph); + var preset = geometry === 'area' && presetManager.match(entity, graph); var icon = preset && !blacklisted(preset) && preset.icon; if (!icon && !utilDisplayName(entity)) @@ -559,7 +559,7 @@ export function svgLabels(projection, context) { if (isNaN(centroid[0]) || areaWidth < 20) return; - var preset = context.presets().match(entity, context.graph()); + var preset = presetManager.match(entity, context.graph()); var picon = preset && preset.icon; var iconSize = 17; var padding = 2; diff --git a/modules/svg/points.js b/modules/svg/points.js index 7ba4fdbc3..80f085c3d 100644 --- a/modules/svg/points.js +++ b/modules/svg/points.js @@ -3,6 +3,7 @@ import { geoScaleToZoom } from '../geo'; import { osmEntity } from '../osm'; import { svgPointTransform } from './helpers'; import { svgTagClasses } from './tag_classes'; +import { presetManager } from '../presets'; export function svgPoints(projection, context) { @@ -141,7 +142,7 @@ export function svgPoints(projection, context) { groups.select('.stroke'); // propagate bound data groups.select('.icon') // propagate bound data .attr('xlink:href', function(entity) { - var preset = context.presets().match(entity, graph); + var preset = presetManager.match(entity, graph); var picon = preset && preset.icon; if (!picon) { diff --git a/modules/svg/vertices.js b/modules/svg/vertices.js index d38e5651e..d7cd23ee4 100644 --- a/modules/svg/vertices.js +++ b/modules/svg/vertices.js @@ -1,6 +1,7 @@ import deepEqual from 'fast-deep-equal'; import { select as d3_select } from 'd3-selection'; +import { presetManager } from '../presets'; import { geoScaleToZoom } from '../geo'; import { osmEntity } from '../osm'; import { svgPassiveVertex, svgPointTransform } from './helpers'; @@ -54,7 +55,7 @@ export function svgVertices(projection, context) { icons[entity.id] = entity.hasInterestingTags() && - context.presets().match(entity, graph).icon; + presetManager.match(entity, graph).icon; return icons[entity.id]; } diff --git a/modules/ui/changeset_editor.js b/modules/ui/changeset_editor.js index afff50a89..6adf1313e 100644 --- a/modules/ui/changeset_editor.js +++ b/modules/ui/changeset_editor.js @@ -1,5 +1,6 @@ import { dispatch as d3_dispatch } from 'd3-dispatch'; +import { presetManager } from '../presets'; import { t } from '../core/localizer'; import { svgIcon } from '../svg/icon'; import { uiCombobox} from './combobox'; @@ -27,7 +28,7 @@ export function uiChangesetEditor(context) { if (!_fieldsArr) { initial = true; - var presets = context.presets(); + var presets = presetManager; _fieldsArr = [ uiField(context, presets.field('comment'), null, { show: true, revert: false }), diff --git a/modules/ui/entity_editor.js b/modules/ui/entity_editor.js index b69da5391..e18387fda 100644 --- a/modules/ui/entity_editor.js +++ b/modules/ui/entity_editor.js @@ -2,6 +2,7 @@ import { dispatch as d3_dispatch } from 'd3-dispatch'; import { event as d3_event } from 'd3-selection'; import deepEqual from 'fast-deep-equal'; +import { presetManager } from '../presets'; import { t, localizer } from '../core/localizer'; import { actionChangeTags } from '../actions/change_tags'; import { modeBrowse } from '../modes/browse'; @@ -318,7 +319,7 @@ export function uiEntityEditor(context) { var entity = graph.hasEntity(_entityIDs[i]); if (!entity) return; - var match = context.presets().match(entity, graph); + var match = presetManager.match(entity, graph); if (!counts[match.id]) counts[match.id] = 0; counts[match.id] += 1; @@ -327,7 +328,7 @@ export function uiEntityEditor(context) { var matches = Object.keys(counts).sort(function(p1, p2) { return counts[p2] - counts[p1]; }).map(function(pID) { - return context.presets().item(pID); + return presetManager.item(pID); }); // A "weak" preset doesn't set any tags. (e.g. "Address") diff --git a/modules/ui/feature_list.js b/modules/ui/feature_list.js index b39ab08ef..b91c456fb 100644 --- a/modules/ui/feature_list.js +++ b/modules/ui/feature_list.js @@ -2,8 +2,9 @@ import { event as d3_event, select as d3_select } from 'd3-selection'; - import * as sexagesimal from '@mapbox/sexagesimal'; + +import { presetManager } from '../presets'; import { t } from '../core/localizer'; import { dmsCoordinatePair } from '../util/units'; import { coreGraph } from '../core/graph'; @@ -154,7 +155,7 @@ export function uiFeatureList(context) { var name = utilDisplayName(entity) || ''; if (name.toLowerCase().indexOf(q) < 0) continue; - var matched = context.presets().match(entity, graph); + var matched = presetManager.match(entity, graph); var type = (matched && matched.name()) || utilDisplayType(entity.id); var extent = entity.extent(graph); var distance = extent ? geoSphericalDistance(visibleCenter, extent.center()) : 0; @@ -191,7 +192,7 @@ export function uiFeatureList(context) { var tempEntity = osmEntity(attrs); var tempGraph = coreGraph([tempEntity]); - var matched = context.presets().match(tempEntity, tempGraph); + var matched = presetManager.match(tempEntity, tempGraph); var type = (matched && matched.name()) || utilDisplayType(id); result.push({ diff --git a/modules/ui/fields/address.js b/modules/ui/fields/address.js index 184b73f50..8425e3e75 100644 --- a/modules/ui/fields/address.js +++ b/modules/ui/fields/address.js @@ -2,6 +2,7 @@ import { dispatch as d3_dispatch } from 'd3-dispatch'; import { select as d3_select } from 'd3-selection'; import * as countryCoder from '@ideditor/country-coder'; +import { presetManager } from '../../presets'; import { fileFetcher } from '../../core/file_fetcher'; import { geoExtent, geoChooseEdge, geoSphericalDistance } from '../../geo'; import { uiCombobox } from '../combobox'; @@ -12,7 +13,7 @@ import { t } from '../../core/localizer'; export function uiFieldAddress(field, context) { var dispatch = d3_dispatch('init', 'change'); var wrap = d3_select(null); - var addrField = context.presets().field('address'); // needed for placeholder strings + var addrField = presetManager.field('address'); // needed for placeholder strings var _isInitialized = false; var _entityIDs = []; diff --git a/modules/ui/fields/input.js b/modules/ui/fields/input.js index 988b765a2..7b5ee751b 100644 --- a/modules/ui/fields/input.js +++ b/modules/ui/fields/input.js @@ -2,6 +2,7 @@ import { dispatch as d3_dispatch } from 'd3-dispatch'; import { select as d3_select, event as d3_event } from 'd3-selection'; import * as countryCoder from '@ideditor/country-coder'; +import { presetManager } from '../../presets'; import { fileFetcher } from '../../core/file_fetcher'; import { t, localizer } from '../../core/localizer'; import { geoExtent } from '../../geo'; @@ -33,7 +34,7 @@ export function uiFieldText(field, context) { function i(selection) { var entity = _entityIDs.length && context.hasEntity(_entityIDs[0]); - var preset = entity && context.presets().match(entity, context.graph()); + var preset = entity && presetManager.match(entity, context.graph()); var isLocked = preset && preset.suggestion && field.id === 'brand'; field.locked(isLocked); diff --git a/modules/ui/fields/localized.js b/modules/ui/fields/localized.js index 0a51c97ad..1da84c267 100644 --- a/modules/ui/fields/localized.js +++ b/modules/ui/fields/localized.js @@ -2,6 +2,7 @@ import { dispatch as d3_dispatch } from 'd3-dispatch'; import { select as d3_select, event as d3_event } from 'd3-selection'; import * as countryCoder from '@ideditor/country-coder'; +import { presetManager } from '../../presets'; import { fileFetcher } from '../../core/file_fetcher'; import { t, localizer } from '../../core/localizer'; import { geoExtent } from '../../geo'; @@ -36,7 +37,7 @@ export function uiFieldLocalized(field, context) { .catch(function() { /* ignore */ }); - var allSuggestions = context.presets().collection.filter(function(p) { + var allSuggestions = presetManager.collection.filter(function(p) { return p.suggestion === true; }); @@ -104,7 +105,7 @@ export function uiFieldLocalized(field, context) { // assume the name has already been confirmed if its source has been researched if (entity.tags['name:etymology:wikidata']) return true; - var preset = context.presets().match(entity, context.graph()); + var preset = presetManager.match(entity, context.graph()); var isSuggestion = preset && preset.suggestion; var showsBrand = preset && preset.originalFields.filter(function(d) { return d.id === 'brand'; @@ -149,7 +150,7 @@ export function uiFieldLocalized(field, context) { calcLocked(); var isLocked = field.locked(); var singularEntity = _entityIDs.length === 1 && context.hasEntity(_entityIDs[0]); - var preset = singularEntity && context.presets().match(singularEntity, context.graph()); + var preset = singularEntity && presetManager.match(singularEntity, context.graph()); var wrap = selection.selectAll('.form-field-input-wrap') .data([0]); @@ -258,7 +259,7 @@ export function uiFieldLocalized(field, context) { var latest = _entityIDs.length === 1 && context.hasEntity(_entityIDs[0]); if (!latest) return; // deleting the entity blurred the field? - var preset = context.presets().match(latest, context.graph()); + var preset = presetManager.match(latest, context.graph()); if (preset && preset.suggestion) return; // already accepted // note: here we are testing against "decorated" names, i.e. 'Starbucks – Cafe' diff --git a/modules/ui/fields/radio.js b/modules/ui/fields/radio.js index 5771ebea4..87df640ee 100644 --- a/modules/ui/fields/radio.js +++ b/modules/ui/fields/radio.js @@ -1,6 +1,7 @@ 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 { uiField } from '../field'; import { utilArrayUnion, utilRebind } from '../../util'; @@ -76,8 +77,8 @@ export function uiFieldRadio(field, context) { function structureExtras(selection, tags) { var selected = selectedKey() || tags.layer !== undefined; - var type = context.presets().field(selected); - var layer = context.presets().field('layer'); + var type = presetManager.field(selected); + var layer = presetManager.field('layer'); var showLayer = (selected === 'bridge' || selected === 'tunnel' || tags.layer !== undefined); diff --git a/modules/ui/fields/restrictions.js b/modules/ui/fields/restrictions.js index fd4c99fbb..af562d76d 100644 --- a/modules/ui/fields/restrictions.js +++ b/modules/ui/fields/restrictions.js @@ -1,6 +1,7 @@ import { dispatch as d3_dispatch } from 'd3-dispatch'; import { select as d3_select, event as d3_event } from 'd3-selection'; +import { presetManager } from '../../presets'; import { prefs } from '../../core/preferences'; import { t, localizer } from '../../core/localizer'; import { actionRestrictTurn } from '../../actions/restrict_turn'; @@ -609,7 +610,7 @@ export function uiFieldRestrictions(field, context) { function displayName(entityID, graph) { var entity = graph.entity(entityID); var name = utilDisplayName(entity) || ''; - var matched = context.presets().match(entity, graph); + var matched = presetManager.match(entity, graph); var type = (matched && matched.name()) || utilDisplayType(entity.id); return name || type; } diff --git a/modules/ui/improveOSM_details.js b/modules/ui/improveOSM_details.js index 80608707f..c5d39acf7 100644 --- a/modules/ui/improveOSM_details.js +++ b/modules/ui/improveOSM_details.js @@ -3,6 +3,7 @@ import { select as d3_select } from 'd3-selection'; +import { presetManager } from '../presets'; import { modeSelect } from '../modes/select'; import { t } from '../core/localizer'; import { utilDisplayName, utilHighlightEntities, utilEntityRoot } from '../util'; @@ -97,7 +98,7 @@ export function uiImproveOsmDetails(context) { let name = utilDisplayName(entity); // try to use common name if (!name && !isObjectLink) { - const preset = context.presets().match(entity, context.graph()); + const preset = presetManager.match(entity, context.graph()); name = preset && !preset.isFallback() && preset.name(); // fallback to preset name } diff --git a/modules/ui/init.js b/modules/ui/init.js index c218f4179..a5525eaea 100644 --- a/modules/ui/init.js +++ b/modules/ui/init.js @@ -5,7 +5,7 @@ import { import { prefs } from '../core/preferences'; import { t, localizer } from '../core/localizer'; - +import { presetManager } from '../presets'; import { behaviorHash } from '../behavior'; import { modeBrowse } from '../modes/browse'; import { svgDefs, svgIcon } from '../svg'; @@ -421,7 +421,7 @@ export function uiInit(context) { return _loadPromise = Promise.all([ // must have strings and presets before loading the UI localizer.ensureLoaded(), - context.presets().ensureLoaded() + presetManager.ensureLoaded() ]) .then(() => { if (!context.container().empty()) render(context.container()); diff --git a/modules/ui/intro/area.js b/modules/ui/intro/area.js index d54fd5e0d..53b4db2c5 100644 --- a/modules/ui/intro/area.js +++ b/modules/ui/intro/area.js @@ -8,6 +8,7 @@ import { interpolateNumber as d3_interpolateNumber } from 'd3-interpolate'; +import { presetManager } from '../../presets'; import { t } from '../../core/localizer'; import { modeBrowse } from '../../modes/browse'; import { modeSelect } from '../../modes/select'; @@ -19,8 +20,8 @@ import { icon, pad, transitionTime } from './helper'; export function uiIntroArea(context, reveal) { var dispatch = d3_dispatch('done'); var playground = [-85.63552, 41.94159]; - var playgroundPreset = context.presets().item('leisure/playground'); - var descriptionField = context.presets().field('description'); + var playgroundPreset = presetManager.item('leisure/playground'); + var descriptionField = presetManager.field('description'); var timeouts = []; var _areaID; diff --git a/modules/ui/intro/building.js b/modules/ui/intro/building.js index 421c949c3..7ed73d0f1 100644 --- a/modules/ui/intro/building.js +++ b/modules/ui/intro/building.js @@ -4,6 +4,7 @@ import { event as d3_event } from 'd3-selection'; +import { presetManager } from '../../presets'; import { t, localizer } from '../../core/localizer'; import { modeBrowse } from '../../modes/browse'; import { modeSelect } from '../../modes/select'; @@ -15,9 +16,9 @@ export function uiIntroBuilding(context, reveal) { var dispatch = d3_dispatch('done'); var house = [-85.62815, 41.95638]; var tank = [-85.62732, 41.95347]; - var buildingCatetory = context.presets().item('category-building'); - var housePreset = context.presets().item('building/house'); - var tankPreset = context.presets().item('man_made/storage_tank'); + var buildingCatetory = presetManager.item('category-building'); + var housePreset = presetManager.item('building/house'); + var tankPreset = presetManager.item('man_made/storage_tank'); var timeouts = []; var _houseID = null; var _tankID = null; diff --git a/modules/ui/intro/intro.js b/modules/ui/intro/intro.js index b89fa40f4..5994ad0e0 100644 --- a/modules/ui/intro/intro.js +++ b/modules/ui/intro/intro.js @@ -1,6 +1,7 @@ import { t, localizer } from '../../core/localizer'; import { localize } from './helper'; +import { presetManager } from '../../presets'; import { prefs } from '../../core/preferences'; import { fileFetcher } from '../../core/file_fetcher'; import { coreGraph } from '../../core/graph'; @@ -124,7 +125,7 @@ export function uiIntro(context) { let chapters = chapterFlow.map((chapter, i) => { let s = chapterUi[chapter](context, curtain.reveal) .on('done', () => { - context.presets().init(); // clear away "recent" presets + presetManager.init(); // clear away "recent" presets buttons .filter(d => d.title === s.title) diff --git a/modules/ui/intro/line.js b/modules/ui/intro/line.js index d0a928bfb..9696c2bcf 100644 --- a/modules/ui/intro/line.js +++ b/modules/ui/intro/line.js @@ -5,6 +5,7 @@ import { select as d3_select } from 'd3-selection'; +import { presetManager } from '../../presets'; import { t, localizer } from '../../core/localizer'; import { geoSphericalDistance } from '../../geo'; import { modeBrowse } from '../../modes/browse'; @@ -21,8 +22,8 @@ export function uiIntroLine(context, reveal) { var tulipRoadStart = [-85.6297754121684, 41.95805253325314]; var tulipRoadMidpoint = [-85.62975395449628, 41.95787501510204]; var tulipRoadIntersection = [-85.62974496187628, 41.95742515554585]; - var roadCategory = context.presets().item('category-road_minor'); - var residentialPreset = context.presets().item('highway/residential'); + var roadCategory = presetManager.item('category-road_minor'); + var residentialPreset = presetManager.item('highway/residential'); var woodRoadID = 'w525'; var woodRoadEndID = 'n2862'; var woodRoadAddNode = [-85.62390110349587, 41.95397111462291]; diff --git a/modules/ui/intro/navigation.js b/modules/ui/intro/navigation.js index 0c8e4d373..235ce9833 100644 --- a/modules/ui/intro/navigation.js +++ b/modules/ui/intro/navigation.js @@ -5,6 +5,7 @@ import { select as d3_select } from 'd3-selection'; +import { presetManager } from '../../presets'; import { t } from '../../core/localizer'; import { modeBrowse } from '../../modes/browse'; import { modeSelect } from '../../modes/select'; @@ -20,8 +21,8 @@ export function uiIntroNavigation(context, reveal) { var springStreetId = 'w397'; var springStreetEndId = 'n1834'; var springStreet = [-85.63582, 41.94255]; - var onewayField = context.presets().field('oneway'); - var maxspeedField = context.presets().field('maxspeed'); + var onewayField = presetManager.field('oneway'); + var maxspeedField = presetManager.field('maxspeed'); var chapter = { @@ -290,7 +291,7 @@ export function uiIntroNavigation(context, reveal) { // preset match, in case the user happened to change it. var entity = context.entity(context.selectedIDs()[0]); - var preset = context.presets().match(entity, context.graph()); + var preset = presetManager.match(entity, context.graph()); var onClick = function() { continueTo(fieldsTownHall); }; diff --git a/modules/ui/intro/point.js b/modules/ui/intro/point.js index 44383c4d0..5cf276787 100644 --- a/modules/ui/intro/point.js +++ b/modules/ui/intro/point.js @@ -4,6 +4,7 @@ import { select as d3_select } from 'd3-selection'; +import { presetManager } from '../../presets'; import { t, localizer } from '../../core/localizer'; import { actionChangePreset } from '../../actions/change_preset'; import { modeBrowse } from '../../modes/browse'; @@ -17,7 +18,7 @@ export function uiIntroPoint(context, reveal) { var timeouts = []; var intersection = [-85.63279, 41.94394]; var building = [-85.632422, 41.944045]; - var cafePreset = context.presets().item('amenity/cafe'); + var cafePreset = presetManager.item('amenity/cafe'); var _pointID = null; @@ -284,7 +285,7 @@ export function uiIntroPoint(context, reveal) { if (!entity) return chapter.restart(); // make sure it's still a cafe, in case user somehow changed it.. - var oldPreset = context.presets().match(entity, context.graph()); + var oldPreset = presetManager.match(entity, context.graph()); context.replace(actionChangePreset(_pointID, oldPreset, cafePreset)); context.enter(modeBrowse(context)); diff --git a/modules/ui/keepRight_details.js b/modules/ui/keepRight_details.js index 34f81d111..23ca20fa3 100644 --- a/modules/ui/keepRight_details.js +++ b/modules/ui/keepRight_details.js @@ -3,6 +3,7 @@ import { select as d3_select } from 'd3-selection'; +import { presetManager } from '../presets'; import { modeSelect } from '../modes/select'; import { t } from '../core/localizer'; import { utilDisplayName, utilHighlightEntities, utilEntityRoot } from '../util'; @@ -102,7 +103,7 @@ export function uiKeepRightDetails(context) { let name = utilDisplayName(entity); // try to use common name if (!name && !isObjectLink) { - const preset = context.presets().match(entity, context.graph()); + const preset = presetManager.match(entity, context.graph()); name = preset && !preset.isFallback() && preset.name(); // fallback to preset name } diff --git a/modules/ui/note_editor.js b/modules/ui/note_editor.js index e85db71d2..f6d0adac9 100644 --- a/modules/ui/note_editor.js +++ b/modules/ui/note_editor.js @@ -113,7 +113,7 @@ export function uiNoteEditor(context) { // // if new note, show categories to pick from // if (_note.isNew()) { - // var presets = context.presets(); + // var presets = presetManager; // // NOTE: this key isn't a age and therefore there is no documentation (yet) // _fieldsArr = [ diff --git a/modules/ui/osmose_details.js b/modules/ui/osmose_details.js index 4038acf4e..bfa7b151c 100644 --- a/modules/ui/osmose_details.js +++ b/modules/ui/osmose_details.js @@ -3,6 +3,7 @@ import { select as d3_select } from 'd3-selection'; +import { presetManager } from '../presets'; import { modeSelect } from '../modes/select'; import { t } from '../core/localizer'; import { services } from '../services'; @@ -180,7 +181,7 @@ export function uiOsmoseDetails(context) { let name = utilDisplayName(entity); // try to use common name if (!name) { - const preset = context.presets().match(entity, context.graph()); + const preset = presetManager.match(entity, context.graph()); name = preset && !preset.isFallback() && preset.name(); // fallback to preset name } diff --git a/modules/ui/preset_icon.js b/modules/ui/preset_icon.js index 5c1aedbb1..d8fe54916 100644 --- a/modules/ui/preset_icon.js +++ b/modules/ui/preset_icon.js @@ -1,11 +1,12 @@ import { select as d3_select } from 'd3-selection'; +import { presetManager } from '../presets'; import { prefs } from '../core/preferences'; import { svgIcon, svgTagClasses } from '../svg'; import { utilFunctor } from '../util'; -export function uiPresetIcon(context) { +export function uiPresetIcon() { let _preset; let _geometry; let _sizeClass = 'medium'; @@ -341,7 +342,7 @@ export function uiPresetIcon(context) { let routeType = p.tags.type === 'waterway' ? 'waterway' : p.tags.route; const segmentPresetIDs = routeSegments[routeType]; for (let i in segmentPresetIDs) { - const segmentPreset = context.presets().item(segmentPresetIDs[i]); + const segmentPreset = presetManager.item(segmentPresetIDs[i]); const segmentTagClasses = svgTagClasses().getClassesString(segmentPreset.tags, ''); route.selectAll(`path.stroke.segment${i}`) .attr('class', `segment${i} line stroke ${segmentTagClasses}`); diff --git a/modules/ui/preset_list.js b/modules/ui/preset_list.js index 7c8fde7e2..d3cca64b8 100644 --- a/modules/ui/preset_list.js +++ b/modules/ui/preset_list.js @@ -6,6 +6,7 @@ import { select as d3_select } from 'd3-selection'; +import { presetManager } from '../presets'; import { t, localizer } from '../core/localizer'; import { actionChangePreset } from '../actions/change_preset'; import { operationDelete } from '../operations/delete'; @@ -27,7 +28,7 @@ export function uiPresetList(context) { function presetList(selection) { if (!_entityIDs) return; - var presets = context.presets().matchAllGeometry(entityGeometries()); + var presets = presetManager.matchAllGeometry(entityGeometries()); selection.html(''); @@ -105,7 +106,7 @@ export function uiPresetList(context) { search: value }); } else { - results = context.presets().defaults(entityGeometries()[0], 36, !context.inIntro()); + results = presetManager.defaults(entityGeometries()[0], 36, !context.inIntro()); messageText = t('inspector.choose'); } list.call(drawList, results); @@ -140,7 +141,7 @@ export function uiPresetList(context) { var list = listWrap .append('div') .attr('class', 'preset-list') - .call(drawList, context.presets().defaults(entityGeometries()[0], 36, !context.inIntro())); + .call(drawList, presetManager.defaults(entityGeometries()[0], 36, !context.inIntro())); context.features().on('change.preset-list', updateForFeatureHiddenState); } @@ -283,7 +284,7 @@ export function uiPresetList(context) { .append('button') .attr('class', 'preset-list-button') .classed('expanded', false) - .call(uiPresetIcon(context) + .call(uiPresetIcon() .geometry(geometries.length === 1 && geometries[0]) .preset(preset)) .on('click', click) @@ -373,7 +374,7 @@ export function uiPresetList(context) { var button = wrap.append('button') .attr('class', 'preset-list-button') - .call(uiPresetIcon(context) + .call(uiPresetIcon() .geometry(geometries.length === 1 && geometries[0]) .preset(preset)) .on('click', item.choose) @@ -400,13 +401,13 @@ export function uiPresetList(context) { item.choose = function() { if (d3_select(this).classed('disabled')) return; if (!context.inIntro()) { - context.presets().setMostRecent(preset, entityGeometries()[0]); + presetManager.setMostRecent(preset, entityGeometries()[0]); } context.perform( function(graph) { for (var i in _entityIDs) { var entityID = _entityIDs[i]; - var oldPreset = context.presets().match(graph.entity(entityID), graph); + var oldPreset = presetManager.match(graph.entity(entityID), graph); graph = actionChangePreset(entityID, oldPreset, preset)(graph); } return graph; @@ -475,7 +476,7 @@ export function uiPresetList(context) { _entityIDs = val; if (_entityIDs && _entityIDs.length) { var presets = _entityIDs.map(function(entityID) { - return context.presets().match(context.entity(entityID), context.graph()); + return presetManager.match(context.entity(entityID), context.graph()); }); presetList.presets(presets); } diff --git a/modules/ui/sections/changes.js b/modules/ui/sections/changes.js index 8b8d3d46c..3be5de18c 100644 --- a/modules/ui/sections/changes.js +++ b/modules/ui/sections/changes.js @@ -1,5 +1,6 @@ import { select as d3_select } from 'd3-selection'; +import { presetManager } from '../../presets'; import { fileFetcher } from '../../core/file_fetcher'; import { t } from '../../core/localizer'; import { JXON } from '../../util/jxon'; @@ -73,7 +74,7 @@ export function uiSectionChanges(context) { .append('strong') .attr('class', 'entity-type') .text(function(d) { - var matched = context.presets().match(d.entity, d.graph); + var matched = presetManager.match(d.entity, d.graph); return (matched && matched.name()) || utilDisplayType(d.entity.id); }); diff --git a/modules/ui/sections/feature_type.js b/modules/ui/sections/feature_type.js index 8c6d9fe49..3bd55a427 100644 --- a/modules/ui/sections/feature_type.js +++ b/modules/ui/sections/feature_type.js @@ -3,6 +3,7 @@ import { event as d3_event } from 'd3-selection'; +import { presetManager } from '../../presets'; import { utilArrayIdentical } from '../../util/array'; import { t } from '../../core/localizer'; import { uiTooltip } from '../tooltip'; @@ -93,9 +94,9 @@ export function uiSectionFeatureType(context) { var geometries = entityGeometries(); selection.select('.preset-list-item button') - .call(uiPresetIcon(context) + .call(uiPresetIcon() .geometry(_presets.length === 1 ? (geometries.length === 1 && geometries[0]) : null) - .preset(_presets.length === 1 ? _presets[0] : context.presets().item('point')) + .preset(_presets.length === 1 ? _presets[0] : presetManager.item('point')) ); // NOTE: split on en-dash, not a hypen (to avoid conflict with hyphenated names) diff --git a/modules/ui/sections/preset_fields.js b/modules/ui/sections/preset_fields.js index 584e1faaa..5e8fb2910 100644 --- a/modules/ui/sections/preset_fields.js +++ b/modules/ui/sections/preset_fields.js @@ -3,6 +3,7 @@ import { event as d3_event } from 'd3-selection'; +import { presetManager } from '../../presets'; import { t, localizer } from '../../core/localizer'; import { utilArrayIdentical } from '../../util/array'; import { utilArrayUnion, utilRebind } from '../../util'; @@ -36,7 +37,7 @@ export function uiSectionPresetFields(context) { return geoms[graph.entity(entityID).geometry(graph)] = true; }, {})); - var presetsManager = context.presets(); + var presetsManager = presetManager; var allFields = []; var allMoreFields = []; diff --git a/modules/ui/sections/raw_member_editor.js b/modules/ui/sections/raw_member_editor.js index 8432f3313..e8597eebd 100644 --- a/modules/ui/sections/raw_member_editor.js +++ b/modules/ui/sections/raw_member_editor.js @@ -4,6 +4,7 @@ import { select as d3_select } from 'd3-selection'; +import { presetManager } from '../../presets'; import { t } from '../../core/localizer'; import { actionChangeMember } from '../../actions/change_member'; import { actionDeleteMember } from '../../actions/delete_member'; @@ -177,7 +178,7 @@ export function uiSectionRawMemberEditor(context) { .append('span') .attr('class', 'member-entity-type') .text(function(d) { - var matched = context.presets().match(d.member, context.graph()); + var matched = presetManager.match(d.member, context.graph()); return (matched && matched.name()) || utilDisplayType(d.member.id); }); diff --git a/modules/ui/sections/raw_membership_editor.js b/modules/ui/sections/raw_membership_editor.js index 88c1c176d..8c93fd134 100644 --- a/modules/ui/sections/raw_membership_editor.js +++ b/modules/ui/sections/raw_membership_editor.js @@ -3,6 +3,7 @@ import { select as d3_select } from 'd3-selection'; +import { presetManager } from '../../presets'; import { t, localizer } from '../../core/localizer'; import { actionAddEntity } from '../../actions/add_entity'; @@ -128,7 +129,7 @@ export function uiSectionRawMembershipEditor(context) { var graph = context.graph(); function baseDisplayLabel(entity) { - var matched = context.presets().match(entity, graph); + var matched = presetManager.match(entity, graph); var presetName = (matched && matched.name()) || t('inspector.relation'); var entityName = utilDisplayName(entity) || ''; @@ -238,7 +239,7 @@ export function uiSectionRawMembershipEditor(context) { .append('span') .attr('class', 'member-entity-type') .text(function(d) { - var matched = context.presets().match(d.relation, context.graph()); + var matched = presetManager.match(d.relation, context.graph()); return (matched && matched.name()) || t('inspector.relation'); }); diff --git a/modules/ui/sections/selection_list.js b/modules/ui/sections/selection_list.js index d66098955..439800976 100644 --- a/modules/ui/sections/selection_list.js +++ b/modules/ui/sections/selection_list.js @@ -1,5 +1,6 @@ import { event as d3_event, select as d3_select } from 'd3-selection'; +import { presetManager } from '../../presets'; import { modeSelect } from '../../modes/select'; import { osmEntity } from '../../osm'; import { svgIcon } from '../../svg/icon'; @@ -118,7 +119,7 @@ export function uiSectionSelectionList(context) { }); items.selectAll('.entity-type') - .text(function(entity) { return context.presets().match(entity, context.graph()).name(); }); + .text(function(entity) { return presetManager.match(entity, context.graph()).name(); }); items.selectAll('.entity-name') .text(function(d) { diff --git a/modules/ui/tools/modes.js b/modules/ui/tools/modes.js index 0fb7c8ca7..46022be10 100644 --- a/modules/ui/tools/modes.js +++ b/modules/ui/tools/modes.js @@ -9,6 +9,7 @@ import { modeBrowse } from '../../modes'; +import { presetManager } from '../../presets'; import { t } from '../../core/localizer'; import { svgIcon } from '../../svg'; import { uiTooltip } from '../tooltip'; @@ -25,21 +26,21 @@ export function uiToolOldDrawModes(context) { title: t('modes.add_point.title'), button: 'point', description: t('modes.add_point.description'), - preset: context.presets().item('point'), + preset: presetManager.item('point'), key: '1' }), modeAddLine(context, { title: t('modes.add_line.title'), button: 'line', description: t('modes.add_line.description'), - preset: context.presets().item('line'), + preset: presetManager.item('line'), key: '2' }), modeAddArea(context, { title: t('modes.add_area.title'), button: 'area', description: t('modes.add_area.description'), - preset: context.presets().item('area'), + preset: presetManager.item('area'), key: '3' }) ]; diff --git a/modules/util/index.js b/modules/util/index.js index e3e6f39be..5364149c5 100644 --- a/modules/util/index.js +++ b/modules/util/index.js @@ -36,7 +36,6 @@ export { utilNoAuto } from './util'; export { utilObjectOmit } from './object'; export { utilPrefixCSSProperty } from './util'; export { utilPrefixDOMProperty } from './util'; -export { utilPreset } from './util'; export { utilQsString } from './util'; export { utilRebind } from './rebind'; export { utilSafeClassName } from './util'; diff --git a/modules/util/util.js b/modules/util/util.js index de227cbbf..5ee8be039 100644 --- a/modules/util/util.js +++ b/modules/util/util.js @@ -1,6 +1,7 @@ import { remove as removeDiacritics } from 'diacritics'; import { fixRTLTextForSvg, rtlRegex } from './svg_paths_rtl_fix'; +import { presetManager } from '../presets'; import { t, localizer } from '../core/localizer'; import { utilArrayUnion } from './array'; import { utilDetect } from './detect'; @@ -206,7 +207,7 @@ export function utilDisplayLabel(entity, context) { // use the display name if there is one return displayName; } - var preset = utilPreset(entity, context); + var preset = presetManager.match(entity, context.graph()); if (preset && preset.name()) { // use the preset name if there is a match return preset.name(); @@ -216,11 +217,6 @@ export function utilDisplayLabel(entity, context) { } -export function utilPreset(entity, context) { - return context.presets().match(entity, context.graph()); -} - - export function utilEntityRoot(entityType) { return { node: 'n', diff --git a/modules/validations/mismatched_geometry.js b/modules/validations/mismatched_geometry.js index 509329d8e..d53d241dd 100644 --- a/modules/validations/mismatched_geometry.js +++ b/modules/validations/mismatched_geometry.js @@ -5,13 +5,14 @@ import { actionExtract } from '../actions/extract'; import { modeSelect } from '../modes/select'; import { osmJoinWays } from '../osm/multipolygon'; import { osmNodeGeometriesForTags } from '../osm/tags'; +import { presetManager } from '../presets'; import { geoHasSelfIntersections, geoSphericalDistance } from '../geo'; import { t } from '../core/localizer'; import { utilDisplayLabel, utilTagText } from '../util'; import { validationIssue, validationIssueFix } from '../core/validation'; -export function validationMismatchedGeometry(context) { +export function validationMismatchedGeometry() { var type = 'mismatched_geometry'; function tagSuggestingLineIsArea(entity) { @@ -22,8 +23,8 @@ export function validationMismatchedGeometry(context) { return null; } - var asLine = context.presets().matchTags(tagSuggestingArea, 'line'); - var asArea = context.presets().matchTags(tagSuggestingArea, 'area'); + var asLine = presetManager.matchTags(tagSuggestingArea, 'line'); + var asArea = presetManager.matchTags(tagSuggestingArea, 'area'); if (asLine && asArea && (asLine === asArea)) { // these tags also allow lines and making this an area wouldn't matter return null; diff --git a/modules/validations/outdated_tags.js b/modules/validations/outdated_tags.js index d4d7974b0..76d022660 100644 --- a/modules/validations/outdated_tags.js +++ b/modules/validations/outdated_tags.js @@ -2,6 +2,7 @@ import { t } from '../core/localizer'; import { matcher } from 'name-suggestion-index'; import * as countryCoder from '@ideditor/country-coder'; +import { presetManager } from '../presets'; import { fileFetcher } from '../core/file_fetcher'; import { actionChangePreset } from '../actions/change_preset'; import { actionChangeTags } from '../actions/change_tags'; @@ -14,7 +15,7 @@ import { validationIssue, validationIssueFix } from '../core/validation'; let _dataDeprecated; let _nsi; -export function validationOutdatedTags(context) { +export function validationOutdatedTags() { const type = 'outdated_tags'; const nsiKeys = ['amenity', 'shop', 'tourism', 'leisure', 'office']; @@ -55,13 +56,13 @@ export function validationOutdatedTags(context) { function oldTagIssues(entity, graph) { const oldTags = Object.assign({}, entity.tags); // shallow copy - let preset = context.presets().match(entity, graph); + let preset = presetManager.match(entity, graph); let subtype = 'deprecated_tags'; if (!preset) return []; // upgrade preset.. if (preset.replacement) { - const newPreset = context.presets().item(preset.replacement); + const newPreset = presetManager.item(preset.replacement); graph = actionChangePreset(entity.id, preset, newPreset)(graph); entity = graph.entity(entity.id); preset = newPreset; diff --git a/modules/validations/suspicious_name.js b/modules/validations/suspicious_name.js index f1a161a26..e03479651 100644 --- a/modules/validations/suspicious_name.js +++ b/modules/validations/suspicious_name.js @@ -1,7 +1,7 @@ import { fileFetcher } from '../core/file_fetcher'; import { localizer } from '../core/localizer'; import { t } from '../core/localizer'; -import { utilPreset } from '../util'; +import { presetManager } from '../presets'; import { validationIssue, validationIssueFix } from '../core/validation'; import { actionChangeTags } from '../actions/change_tags'; @@ -59,7 +59,7 @@ export function validationSuspiciousName() { message: function(context) { let entity = context.hasEntity(this.entityIds[0]); if (!entity) return ''; - let preset = utilPreset(entity, context); + let preset = presetManager.match(entity, context.graph()); let langName = langCode && localizer.languageName(langCode); return t('issues.generic_name.message' + (langName ? '_language' : ''), { feature: preset.name(), name: genericName, language: langName } @@ -105,7 +105,7 @@ export function validationSuspiciousName() { message: function(context) { const entity = context.hasEntity(this.entityIds[0]); if (!entity) return ''; - const preset = utilPreset(entity, context); + const preset = presetManager.match(entity, context.graph()); const langName = langCode && localizer.languageName(langCode); return t('issues.incorrect_name.message' + (langName ? '_language' : ''), { feature: preset.name(), name: incorrectName, language: langName } diff --git a/test/spec/presets/index.js b/test/spec/presets/index.js index aa65d0a79..9424bfa90 100644 --- a/test/spec/presets/index.js +++ b/test/spec/presets/index.js @@ -16,27 +16,27 @@ describe('iD.presetIndex', function () { it('has a fallback point preset', function () { var node = iD.osmNode({ id: 'n' }); var graph = iD.coreGraph([node]); - var presets = iD.coreContext().init().presets(); + var presets = iD.presetIndex(); expect(presets.match(node, graph).id).to.eql('point'); }); it('has a fallback line preset', function () { var node = iD.osmNode({ id: 'n' }); var way = iD.osmWay({ id: 'w', nodes: ['n'] }); var graph = iD.coreGraph([node, way]); - var presets = iD.coreContext().init().presets(); + var presets = iD.presetIndex(); expect(presets.match(way, graph).id).to.eql('line'); }); it('has a fallback area preset', function () { var node = iD.osmNode({ id: 'n' }); var way = iD.osmWay({ id: 'w', nodes: ['n'], tags: { area: 'yes' }}); var graph = iD.coreGraph([node, way]); - var presets = iD.coreContext().init().presets(); + var presets = iD.presetIndex(); expect(presets.match(way, graph).id).to.eql('area'); }); it('has a fallback relation preset', function () { var relation = iD.osmRelation({ id: 'r' }); var graph = iD.coreGraph([relation]); - var presets = iD.coreContext().init().presets(); + var presets = iD.presetIndex(); expect(presets.match(relation, graph).id).to.eql('relation'); }); }); @@ -50,7 +50,7 @@ describe('iD.presetIndex', function () { it('returns a collection containing presets matching a geometry and tags', function (done) { iD.fileFetcher.cache().preset_presets = testPresets; - var presets = iD.coreContext().init().presets(); + var presets = iD.presetIndex(); presets.ensureLoaded().then(function() { var way = iD.osmWay({ tags: { highway: 'residential' } }); var graph = iD.coreGraph([way]); @@ -61,7 +61,7 @@ describe('iD.presetIndex', function () { it('returns the appropriate fallback preset when no tags match', function (done) { iD.fileFetcher.cache().preset_presets = testPresets; - var presets = iD.coreContext().init().presets(); + var presets = iD.presetIndex(); var point = iD.osmNode(); var line = iD.osmWay({ tags: { foo: 'bar' } }); var graph = iD.coreGraph([point, line]); @@ -75,7 +75,7 @@ describe('iD.presetIndex', function () { it('matches vertices on a line as points', function (done) { iD.fileFetcher.cache().preset_presets = testPresets; - var presets = iD.coreContext().init().presets(); + var presets = iD.presetIndex(); var point = iD.osmNode({ tags: { leisure: 'park' } }); var line = iD.osmWay({ nodes: [point.id], tags: { 'highway': 'residential' } }); var graph = iD.coreGraph([point, line]); @@ -88,7 +88,7 @@ describe('iD.presetIndex', function () { it('matches vertices on an addr:interpolation line as points', function (done) { iD.fileFetcher.cache().preset_presets = testPresets; - var presets = iD.coreContext().init().presets(); + var presets = iD.presetIndex(); var point = iD.osmNode({ tags: { leisure: 'park' } }); var line = iD.osmWay({ nodes: [point.id], tags: { 'addr:interpolation': 'even' } }); var graph = iD.coreGraph([point, line]); @@ -114,7 +114,7 @@ describe('iD.presetIndex', function () { it('includes keys for presets with area geometry', function (done) { iD.fileFetcher.cache().preset_presets = testPresets; - var presets = iD.coreContext().init().presets(); + var presets = iD.presetIndex(); presets.ensureLoaded().then(function() { expect(presets.areaKeys()).to.include.keys('natural'); done(); @@ -123,7 +123,7 @@ describe('iD.presetIndex', function () { it('discards key-values for presets with a line geometry', function (done) { iD.fileFetcher.cache().preset_presets = testPresets; - var presets = iD.coreContext().init().presets(); + var presets = iD.presetIndex(); presets.ensureLoaded().then(function() { expect(presets.areaKeys().natural).to.include.keys('tree_row'); expect(presets.areaKeys().natural.tree_row).to.be.true; @@ -133,7 +133,7 @@ describe('iD.presetIndex', function () { it('discards key-values for presets with both area and line geometry', function (done) { iD.fileFetcher.cache().preset_presets = testPresets; - var presets = iD.coreContext().init().presets(); + var presets = iD.presetIndex(); presets.ensureLoaded().then(function() { expect(presets.areaKeys().leisure).to.include.keys('track'); done(); @@ -142,7 +142,7 @@ describe('iD.presetIndex', function () { it('does not discard key-values for presets with neither area nor line geometry', function (done) { iD.fileFetcher.cache().preset_presets = testPresets; - var presets = iD.coreContext().init().presets(); + var presets = iD.presetIndex(); presets.ensureLoaded().then(function() { expect(presets.areaKeys().natural).not.to.include.keys('peak'); done(); @@ -151,7 +151,7 @@ describe('iD.presetIndex', function () { it('does not discard generic \'*\' key-values', function (done) { iD.fileFetcher.cache().preset_presets = testPresets; - var presets = iD.coreContext().init().presets(); + var presets = iD.presetIndex(); presets.ensureLoaded().then(function() { expect(presets.areaKeys().natural).not.to.include.keys('natural'); done(); @@ -160,7 +160,7 @@ describe('iD.presetIndex', function () { it('ignores keys like \'highway\' that are assumed to be lines', function (done) { iD.fileFetcher.cache().preset_presets = testPresets; - var presets = iD.coreContext().init().presets(); + var presets = iD.presetIndex(); presets.ensureLoaded().then(function() { expect(presets.areaKeys()).not.to.include.keys('highway'); done(); @@ -169,7 +169,7 @@ describe('iD.presetIndex', function () { it('ignores suggestion presets', function (done) { iD.fileFetcher.cache().preset_presets = testPresets; - var presets = iD.coreContext().init().presets(); + var presets = iD.presetIndex(); presets.ensureLoaded().then(function() { expect(presets.areaKeys()).not.to.include.keys('amenity'); done(); @@ -180,22 +180,28 @@ describe('iD.presetIndex', function () { describe('#addablePresetIDs', function () { it('addablePresetIDs is initially null', function () { - var presets = iD.coreContext().init().presets(); - expect(presets.addablePresetIDs()).to.be.null; + var presets = iD.presetIndex(); + presets.ensureLoaded().then(function() { + expect(presets.addablePresetIDs()).to.be.null; + done(); + }); }); it('can set and get addablePresetIDs', function () { - var presets = iD.coreContext().init().presets(); - var ids = new Set(['point']); // can only add points - presets.addablePresetIDs(ids); + var presets = iD.presetIndex(); + presets.ensureLoaded().then(function() { + var ids = new Set(['point']); // can only add points + presets.addablePresetIDs(ids); - expect(presets.item('point').addable()).to.be.true; - expect(presets.item('line').addable()).to.be.false; - expect(presets.addablePresetIDs()).to.eql(ids); + expect(presets.item('point').addable()).to.be.true; + expect(presets.item('line').addable()).to.be.false; + expect(presets.addablePresetIDs()).to.eql(ids); - presets.addablePresetIDs(null); - expect(presets.item('point').addable()).to.be.true; - expect(presets.item('line').addable()).to.be.true; + presets.addablePresetIDs(null); + expect(presets.item('point').addable()).to.be.true; + expect(presets.item('line').addable()).to.be.true; + done(); + }); }); }); @@ -204,7 +210,7 @@ describe('iD.presetIndex', function () { it('builds presets from provided', function () { var surfShop = iD.osmNode({ tags: { amenity: 'shop', 'shop:type': 'surf' } }); var graph = iD.coreGraph([surfShop]); - var presets = iD.coreContext().init().presets(); + var presets = iD.presetIndex(); var presetData = { presets: { 'amenity/shop/surf': { @@ -224,7 +230,7 @@ describe('iD.presetIndex', function () { var firstStreetJetty = iD.osmNode({ tags: { man_made: 'jetty' } }); var entities = [surfShop, firstStreetJetty]; var graph = iD.coreGraph(entities); - var presets = iD.coreContext().init().presets(); + var presets = iD.presetIndex(); var presetData = { presets: { 'amenity/shop/surf': { @@ -272,7 +278,7 @@ describe('iD.presetIndex', function () { it('prefers building to multipolygon', function (done) { iD.fileFetcher.cache().preset_presets = testPresets; - var presets = iD.coreContext().init().presets(); + var presets = iD.presetIndex(); var relation = iD.osmRelation({ tags: { type: 'multipolygon', building: 'yes' } }); var graph = iD.coreGraph([relation]); presets.ensureLoaded().then(function() { @@ -284,7 +290,7 @@ describe('iD.presetIndex', function () { it('prefers building to address', function (done) { iD.fileFetcher.cache().preset_presets = testPresets; - var presets = iD.coreContext().init().presets(); + var presets = iD.presetIndex(); var way = iD.osmWay({ tags: { area: 'yes', building: 'yes', 'addr:housenumber': '1234' } }); var graph = iD.coreGraph([way]); presets.ensureLoaded().then(function() { @@ -296,7 +302,7 @@ describe('iD.presetIndex', function () { it('prefers pedestrian to area', function (done) { iD.fileFetcher.cache().preset_presets = testPresets; - var presets = iD.coreContext().init().presets(); + var presets = iD.presetIndex(); var way = iD.osmWay({ tags: { area: 'yes', highway: 'pedestrian' } }); var graph = iD.coreGraph([way]); presets.ensureLoaded().then(function() { @@ -344,13 +350,13 @@ describe('iD.presetIndex', function () { var url = 'https://fakemaprules.io/fake.json'; // no exernal presets yet - expect(iD.coreContext().init().presets().match(surfShop, graph).id).to.eql('point'); + expect(iD.presetIndex().match(surfShop, graph).id).to.eql('point'); // reset graph... graph = iD.coreGraph([surfShop]); // add the validations query param... - iD.coreContext().init().presets().fromExternal(url, function (externalPresets) { + iD.presetIndex().fromExternal(url, function (externalPresets) { expect(externalPresets.match(surfShop, graph).id).to.eql('8bc64d6d'); }); @@ -363,7 +369,7 @@ describe('iD.presetIndex', function () { it('makes only the external presets initially addable', function () { var url = 'https://fakemaprules.io/fake.json'; - iD.coreContext().init().presets().fromExternal(url, function(externalPresets) { + iD.presetIndex().fromExternal(url, function(externalPresets) { var external = externalPresets.collection.reduce(function(presets, preset) { if (!preset.hasOwnProperty('members') && preset.addable()) { presets.push(preset.id);