forked from MapComplete/MapComplete
Search: close dialog when appropriate, move special layer logic to themeViewState
This commit is contained in:
parent
902a479e3b
commit
05e5a63a12
11 changed files with 165 additions and 81 deletions
|
@ -11657,6 +11657,48 @@
|
|||
"question": "Show the raw OpenStreetMap-tags?",
|
||||
"questionHint": "<b>Tags</b> are attributes that every element has. This is the technical data that is stored in the database. You don't need this information to edit with MapComplete, but advanced users might want to use this as reference."
|
||||
},
|
||||
"sync-visited-locations": {
|
||||
"mappings": {
|
||||
"0": {
|
||||
"then": "Save the locations you search for and inspect and sync them via openstreetmap.org. OpenStreetMap and all apps you use can see this history"
|
||||
},
|
||||
"1": {
|
||||
"then": "Save the locations you search for and inspect on my device"
|
||||
},
|
||||
"2": {
|
||||
"then": "Don't save the locations you search for and inspect "
|
||||
}
|
||||
},
|
||||
"question": "Should the locations you search for and inspect be remembered?",
|
||||
"questionHint": "Those locations will be offered in the search menu"
|
||||
},
|
||||
"sync-visited-themes": {
|
||||
"mappings": {
|
||||
"0": {
|
||||
"then": "Save the visited thematic maps and sync them via openstreetmap.org. OpenStreetMap and all apps you use can see this history"
|
||||
},
|
||||
"1": {
|
||||
"then": "Save the visited thematic maps on my device"
|
||||
},
|
||||
"2": {
|
||||
"then": "Don't save visited thematic maps"
|
||||
}
|
||||
},
|
||||
"question": "Should the thematic maps you visit be saved?",
|
||||
"questionHint": "If you visit a map about a certain topic, MapComplete can remember this and offer this as suggestion."
|
||||
},
|
||||
"title-editing": {
|
||||
"render": "<h3>Editing settings</h3>"
|
||||
},
|
||||
"title-id": {
|
||||
"render": "<h3>Mangrove ID management</h3>"
|
||||
},
|
||||
"title-map": {
|
||||
"render": "<h3>Configure map</h3>"
|
||||
},
|
||||
"title-privacy-legal": {
|
||||
"render": "<h3>Privacy and legal</h3>"
|
||||
},
|
||||
"translation-completeness": {
|
||||
"mappings": {
|
||||
"0": {
|
||||
|
|
|
@ -70,7 +70,11 @@ export class OsmPreferences {
|
|||
this.setPreferencesAll(key, initialValue)
|
||||
}
|
||||
pref.addCallback(v => {
|
||||
length.set(Math.ceil(v.length / maxLength))
|
||||
if(v === null || v === undefined || v === ""){
|
||||
length.set(null)
|
||||
return
|
||||
}
|
||||
length.set(Math.ceil((v?.length ?? 1) / maxLength))
|
||||
let i = 0
|
||||
while (v.length > 0) {
|
||||
this.UploadPreference(key + "-" + i, v.substring(0, maxLength))
|
||||
|
@ -97,6 +101,7 @@ export class OsmPreferences {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* OSM preferences can be at most 255 chars.
|
||||
* This method chains multiple together.
|
||||
|
|
|
@ -4,6 +4,8 @@ import Locale from "../../UI/i18n/Locale"
|
|||
import Constants from "../../Models/Constants"
|
||||
import FilterConfig, { FilterConfigOption } from "../../Models/ThemeConfig/FilterConfig"
|
||||
import LayerConfig from "../../Models/ThemeConfig/LayerConfig"
|
||||
import LayerState from "../State/LayerState"
|
||||
import LayoutConfig from "../../Models/ThemeConfig/LayoutConfig"
|
||||
|
||||
export type FilterSearchResult = { option: FilterConfigOption, filter: FilterConfig, layer: LayerConfig, index: number }
|
||||
|
||||
|
@ -12,9 +14,9 @@ export type FilterSearchResult = { option: FilterConfigOption, filter: FilterCon
|
|||
* Searches matching filters
|
||||
*/
|
||||
export default class FilterSearch {
|
||||
private readonly _state: SpecialVisualizationState
|
||||
private readonly _state: {layerState: LayerState, layout: LayoutConfig}
|
||||
|
||||
constructor(state: SpecialVisualizationState) {
|
||||
constructor(state: {layerState: LayerState, layout: LayoutConfig}) {
|
||||
this._state = state
|
||||
}
|
||||
|
||||
|
|
|
@ -1,16 +1,16 @@
|
|||
import { SpecialVisualizationState } from "../../UI/SpecialVisualization"
|
||||
import Constants from "../../Models/Constants"
|
||||
import SearchUtils from "./SearchUtils"
|
||||
import ThemeSearch from "./ThemeSearch"
|
||||
import LayerConfig from "../../Models/ThemeConfig/LayerConfig"
|
||||
import LayoutConfig from "../../Models/ThemeConfig/LayoutConfig"
|
||||
|
||||
export default class LayerSearch {
|
||||
|
||||
private readonly _state: SpecialVisualizationState
|
||||
private readonly _layout: LayoutConfig
|
||||
private readonly _layerWhitelist : Set<string>
|
||||
constructor(state: SpecialVisualizationState) {
|
||||
this._state = state
|
||||
this._layerWhitelist = new Set(state.layout.layers.map(l => l.id).filter(id => Constants.added_by_default.indexOf(<any> id) < 0))
|
||||
constructor(layout: LayoutConfig) {
|
||||
this._layout = layout
|
||||
this._layerWhitelist = new Set(layout.layers.map(l => l.id).filter(id => Constants.added_by_default.indexOf(<any> id) < 0))
|
||||
}
|
||||
|
||||
static scoreLayers(query: string, layerWhitelist?: Set<string>): Record<string, number> {
|
||||
|
@ -35,7 +35,7 @@ export default class LayerSearch {
|
|||
const asList:({layer: LayerConfig, score:number})[] = []
|
||||
for (const layer in scores) {
|
||||
asList.push({
|
||||
layer: this._state.layout.getLayer(layer),
|
||||
layer: this._layout.getLayer(layer),
|
||||
score: scores[layer]
|
||||
})
|
||||
}
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
import { MinimalLayoutInformation } from "../../Models/ThemeConfig/LayoutConfig"
|
||||
import { SpecialVisualizationState } from "../../UI/SpecialVisualization"
|
||||
import LayoutConfig, { MinimalLayoutInformation } from "../../Models/ThemeConfig/LayoutConfig"
|
||||
import { Store } from "../UIEventSource"
|
||||
import UserRelatedState from "../State/UserRelatedState"
|
||||
import { Utils } from "../../Utils"
|
||||
|
@ -7,6 +6,7 @@ import Locale from "../../UI/i18n/Locale"
|
|||
import themeOverview from "../../assets/generated/theme_overview.json"
|
||||
import LayerSearch from "./LayerSearch"
|
||||
import SearchUtils from "./SearchUtils"
|
||||
import { OsmConnection } from "../Osm/OsmConnection"
|
||||
|
||||
|
||||
type ThemeSearchScore = {
|
||||
|
@ -22,7 +22,7 @@ export default class ThemeSearch {
|
|||
public static readonly officialThemes: {
|
||||
themes: MinimalLayoutInformation[],
|
||||
layers: Record<string, Record<string, string[]>>
|
||||
} = themeOverview
|
||||
} = <any> themeOverview
|
||||
public static readonly officialThemesById: Map<string, MinimalLayoutInformation> = new Map<string, MinimalLayoutInformation>()
|
||||
static {
|
||||
for (const th of ThemeSearch.officialThemes.themes ?? []) {
|
||||
|
@ -31,15 +31,13 @@ export default class ThemeSearch {
|
|||
}
|
||||
|
||||
|
||||
private readonly _state: SpecialVisualizationState
|
||||
private readonly _knownHiddenThemes: Store<Set<string>>
|
||||
private readonly _layersToIgnore: string[]
|
||||
private readonly _otherThemes: MinimalLayoutInformation[]
|
||||
|
||||
constructor(state: SpecialVisualizationState) {
|
||||
this._state = state
|
||||
constructor(state: {osmConnection: OsmConnection, layout: LayoutConfig}) {
|
||||
this._layersToIgnore = state.layout.layers.map(l => l.id)
|
||||
this._knownHiddenThemes = UserRelatedState.initDiscoveredHiddenThemes(this._state.osmConnection).map(list => new Set(list))
|
||||
this._knownHiddenThemes = UserRelatedState.initDiscoveredHiddenThemes(state.osmConnection).map(list => new Set(list))
|
||||
this._otherThemes = ThemeSearch.officialThemes.themes
|
||||
.filter(th => th.id !== state.layout.id)
|
||||
}
|
||||
|
@ -144,7 +142,7 @@ export default class ThemeSearch {
|
|||
return scored
|
||||
}
|
||||
|
||||
public static sortedByLowest(search: string, themes: MinimalLayoutInformation[], ignoreLayers: string[] = [], maxDiff: number): MinimalLayoutInformation[] {
|
||||
public static sortedByLowest(search: string, themes: MinimalLayoutInformation[], ignoreLayers: string[] = []): MinimalLayoutInformation[] {
|
||||
return this.sortedByLowestScores(search, themes, ignoreLayers)
|
||||
.map(th => th.theme)
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import GeocodingProvider, { GeocodingUtils, type SearchResult } from "../Search/GeocodingProvider"
|
||||
import GeocodingProvider, { type SearchResult } from "../Search/GeocodingProvider"
|
||||
import { ImmutableStore, Store, Stores, UIEventSource } from "../UIEventSource"
|
||||
import CombinedSearcher from "../Search/CombinedSearcher"
|
||||
import FilterSearch, { FilterSearchResult } from "../Search/FilterSearch"
|
||||
|
@ -11,9 +11,10 @@ import ThemeViewState from "../../Models/ThemeViewState"
|
|||
import type { MinimalLayoutInformation } from "../../Models/ThemeConfig/LayoutConfig"
|
||||
import { Translation } from "../../UI/i18n/Translation"
|
||||
import GeocodingFeatureSource from "../Search/GeocodingFeatureSource"
|
||||
import ShowDataLayer from "../../UI/Map/ShowDataLayer"
|
||||
import LayerSearch from "../Search/LayerSearch"
|
||||
import LayerConfig from "../../Models/ThemeConfig/LayerConfig"
|
||||
import { FeatureSource } from "../FeatureSource/FeatureSource"
|
||||
import { Feature } from "geojson"
|
||||
|
||||
export default class SearchState {
|
||||
|
||||
|
@ -29,6 +30,7 @@ export default class SearchState {
|
|||
private readonly state: ThemeViewState
|
||||
public readonly showSearchDrawer: UIEventSource<boolean>
|
||||
public readonly suggestionsSearchRunning: Store<boolean>
|
||||
public readonly locationResults: FeatureSource
|
||||
|
||||
constructor(state: ThemeViewState) {
|
||||
this.state = state
|
||||
|
@ -62,7 +64,7 @@ export default class SearchState {
|
|||
const themeSearch = new ThemeSearch(state)
|
||||
this.themeSuggestions = this.searchTerm.mapD(query => themeSearch.search(query, 3))
|
||||
|
||||
const layerSearch = new LayerSearch(state)
|
||||
const layerSearch = new LayerSearch(state.layout)
|
||||
this.layerSuggestions = this.searchTerm.mapD(query => layerSearch.search(query, 5))
|
||||
|
||||
const filterSearch = new FilterSearch(state)
|
||||
|
@ -77,17 +79,7 @@ export default class SearchState {
|
|||
return !foundMatch
|
||||
})
|
||||
}, [state.layerState.activeFilters])
|
||||
const geocodedFeatures = new GeocodingFeatureSource(this.suggestions.stabilized(250))
|
||||
state.featureProperties.trackFeatureSource(geocodedFeatures)
|
||||
|
||||
new ShowDataLayer(
|
||||
state.map,
|
||||
{
|
||||
layer: GeocodingUtils.searchLayer,
|
||||
features: geocodedFeatures,
|
||||
selectedElement: state.selectedElement,
|
||||
},
|
||||
)
|
||||
this.locationResults =new GeocodingFeatureSource(this.suggestions.stabilized(250))
|
||||
|
||||
this.showSearchDrawer = new UIEventSource(false)
|
||||
|
||||
|
@ -131,4 +123,19 @@ export default class SearchState {
|
|||
}
|
||||
}
|
||||
|
||||
closeIfFullscreen() {
|
||||
if(window.innerWidth < 640){
|
||||
this.showSearchDrawer.set(false)
|
||||
}
|
||||
}
|
||||
|
||||
clickedOnMap(feature: Feature) {
|
||||
const osmid = feature.properties.osm_id
|
||||
const localElement = this.state.indexedFeatures.featuresById.data.get(osmid)
|
||||
if(localElement){
|
||||
this.state.selectedElement.set(localElement)
|
||||
return
|
||||
}
|
||||
console.log(">>>",feature)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -26,6 +26,7 @@ export default class Constants {
|
|||
"last_click",
|
||||
"favourite",
|
||||
"summary",
|
||||
"search"
|
||||
] as const
|
||||
/**
|
||||
* Special layers which are not included in a theme by default
|
||||
|
@ -39,7 +40,6 @@ export default class Constants {
|
|||
"usersettings",
|
||||
"icons",
|
||||
"filters",
|
||||
"search"
|
||||
] as const
|
||||
/**
|
||||
* Layer IDs of layers which have special properties through built-in hooks
|
||||
|
|
|
@ -58,7 +58,7 @@ import { GeolocationControlState } from "../UI/BigComponents/GeolocationControl"
|
|||
import Zoomcontrol from "../UI/Zoomcontrol"
|
||||
import {
|
||||
SummaryTileSource,
|
||||
SummaryTileSourceRewriter,
|
||||
SummaryTileSourceRewriter
|
||||
} from "../Logic/FeatureSource/TiledFeatureSource/SummaryTileSource"
|
||||
import summaryLayer from "../assets/generated/layers/summary.json"
|
||||
import last_click_layerconfig from "../assets/generated/layers/last_click.json"
|
||||
|
@ -69,6 +69,7 @@ import { GeoOperations } from "../Logic/GeoOperations"
|
|||
import { CombinedFetcher } from "../Logic/Web/NearbyImagesSearch"
|
||||
import { GeocodeResult, GeocodingUtils } from "../Logic/Search/GeocodingProvider"
|
||||
import SearchState from "../Logic/State/SearchState"
|
||||
import { ShowDataLayerOptions } from "../UI/Map/ShowDataLayerOptions"
|
||||
|
||||
/**
|
||||
*
|
||||
|
@ -175,7 +176,7 @@ export default class ThemeViewState implements SpecialVisualizationState {
|
|||
"oauth_token",
|
||||
undefined,
|
||||
"Used to complete the login"
|
||||
),
|
||||
)
|
||||
})
|
||||
this.userRelatedState = new UserRelatedState(
|
||||
this.osmConnection,
|
||||
|
@ -254,8 +255,8 @@ export default class ThemeViewState implements SpecialVisualizationState {
|
|||
bbox.asGeoJson({
|
||||
zoom: this.mapProperties.zoom.data,
|
||||
...this.mapProperties.location.data,
|
||||
id: "current_view_" + currentViewIndex,
|
||||
}),
|
||||
id: "current_view_" + currentViewIndex
|
||||
})
|
||||
]
|
||||
})
|
||||
)
|
||||
|
@ -272,7 +273,7 @@ export default class ThemeViewState implements SpecialVisualizationState {
|
|||
featurePropertiesStore: this.featureProperties,
|
||||
osmConnection: this.osmConnection,
|
||||
historicalUserLocations: this.geolocation.historicalUserLocations,
|
||||
featureSwitches: this.featureSwitches,
|
||||
featureSwitches: this.featureSwitches
|
||||
},
|
||||
layout?.isLeftRightSensitive() ?? false,
|
||||
(e, extraMsg) => this.reportError(e, extraMsg)
|
||||
|
@ -300,7 +301,7 @@ export default class ThemeViewState implements SpecialVisualizationState {
|
|||
"leftover features, such as",
|
||||
features[0].properties
|
||||
)
|
||||
},
|
||||
}
|
||||
}
|
||||
)
|
||||
this.perLayer = perLayer.perLayer
|
||||
|
@ -356,7 +357,7 @@ export default class ThemeViewState implements SpecialVisualizationState {
|
|||
{
|
||||
currentZoom: this.mapProperties.zoom,
|
||||
layerState: this.layerState,
|
||||
bounds: this.visualFeedbackViewportBounds,
|
||||
bounds: this.visualFeedbackViewportBounds
|
||||
}
|
||||
)
|
||||
this.hasDataInView = new NoElementsInViewDetector(this).hasFeatureInView
|
||||
|
@ -453,7 +454,7 @@ export default class ThemeViewState implements SpecialVisualizationState {
|
|||
doShowLayer,
|
||||
metaTags: this.userRelatedState.preferencesAsTags,
|
||||
selectedElement: this.selectedElement,
|
||||
fetchStore: (id) => this.featureProperties.getStore(id),
|
||||
fetchStore: (id) => this.featureProperties.getStore(id)
|
||||
})
|
||||
})
|
||||
return filteringFeatureSource
|
||||
|
@ -480,7 +481,7 @@ export default class ThemeViewState implements SpecialVisualizationState {
|
|||
doShowLayer: flayerGps.isDisplayed,
|
||||
layer: flayerGps.layerDef,
|
||||
metaTags: this.userRelatedState.preferencesAsTags,
|
||||
selectedElement: this.selectedElement,
|
||||
selectedElement: this.selectedElement
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -554,16 +555,16 @@ export default class ThemeViewState implements SpecialVisualizationState {
|
|||
this.previewedImage.setData(undefined)
|
||||
return
|
||||
}
|
||||
if(this.selectedElement.data){
|
||||
if (this.selectedElement.data) {
|
||||
this.selectedElement.setData(undefined)
|
||||
return
|
||||
}
|
||||
if (this.searchState.showSearchDrawer.data){
|
||||
if (this.searchState.showSearchDrawer.data) {
|
||||
this.searchState.showSearchDrawer.set(false)
|
||||
return
|
||||
}
|
||||
if (this.guistate.closeAll()){
|
||||
return
|
||||
if (this.guistate.closeAll()) {
|
||||
return
|
||||
}
|
||||
Zoomcontrol.resetzoom()
|
||||
this.focusOnMap()
|
||||
|
@ -573,10 +574,11 @@ export default class ThemeViewState implements SpecialVisualizationState {
|
|||
this.guistate.pageStates.favourites.set(true)
|
||||
})
|
||||
|
||||
|
||||
Hotkeys.RegisterHotkey(
|
||||
{
|
||||
nomod: " ",
|
||||
onUp: true,
|
||||
onUp: true
|
||||
},
|
||||
docs.selectItem,
|
||||
() => {
|
||||
|
@ -586,7 +588,7 @@ export default class ThemeViewState implements SpecialVisualizationState {
|
|||
if (this.guistate.isSomethingOpen() || this.previewedImage.data !== undefined) {
|
||||
return
|
||||
}
|
||||
if(document.activeElement.tagName === "button" || document.activeElement.tagName === "input"){
|
||||
if (document.activeElement.tagName === "button" || document.activeElement.tagName === "input") {
|
||||
return
|
||||
}
|
||||
this.selectClosestAtCenter(0)
|
||||
|
@ -605,7 +607,7 @@ export default class ThemeViewState implements SpecialVisualizationState {
|
|||
Hotkeys.RegisterHotkey(
|
||||
{
|
||||
nomod: "" + i,
|
||||
onUp: true,
|
||||
onUp: true
|
||||
},
|
||||
doc,
|
||||
() => this.selectClosestAtCenter(i - 1)
|
||||
|
@ -624,7 +626,7 @@ export default class ThemeViewState implements SpecialVisualizationState {
|
|||
}
|
||||
Hotkeys.RegisterHotkey(
|
||||
{
|
||||
nomod: "b",
|
||||
nomod: "b"
|
||||
},
|
||||
docs.openLayersPanel,
|
||||
() => {
|
||||
|
@ -635,7 +637,7 @@ export default class ThemeViewState implements SpecialVisualizationState {
|
|||
)
|
||||
Hotkeys.RegisterHotkey(
|
||||
{
|
||||
nomod: "s",
|
||||
nomod: "s"
|
||||
},
|
||||
Translations.t.hotkeyDocumentation.openFilterPanel,
|
||||
() => {
|
||||
|
@ -713,7 +715,7 @@ export default class ThemeViewState implements SpecialVisualizationState {
|
|||
|
||||
Hotkeys.RegisterHotkey(
|
||||
{
|
||||
shift: "T",
|
||||
shift: "T"
|
||||
},
|
||||
Translations.t.hotkeyDocumentation.translationMode,
|
||||
() => {
|
||||
|
@ -750,7 +752,7 @@ export default class ThemeViewState implements SpecialVisualizationState {
|
|||
this.mapProperties.zoom.map((z) => Math.max(Math.floor(z), 0)),
|
||||
this.mapProperties,
|
||||
{
|
||||
isActive: this.mapProperties.zoom.map((z) => z < maxzoom),
|
||||
isActive: this.mapProperties.zoom.map((z) => z < maxzoom)
|
||||
}
|
||||
)
|
||||
|
||||
|
@ -783,6 +785,7 @@ export default class ThemeViewState implements SpecialVisualizationState {
|
|||
favourite: this.favourites,
|
||||
summary: this.featureSummary,
|
||||
last_click: this.lastClickObject,
|
||||
search: this.searchState.locationResults
|
||||
}
|
||||
|
||||
this.closestFeatures.registerSource(specialLayers.favourite, "favourite")
|
||||
|
@ -832,20 +835,28 @@ export default class ThemeViewState implements SpecialVisualizationState {
|
|||
}
|
||||
|
||||
this.featureProperties.trackFeatureSource(features)
|
||||
new ShowDataLayer(this.map, {
|
||||
const options: ShowDataLayerOptions & { layer: LayerConfig } = {
|
||||
features,
|
||||
doShowLayer: flayer.isDisplayed,
|
||||
layer: flayer.layerDef,
|
||||
metaTags: this.userRelatedState.preferencesAsTags,
|
||||
selectedElement: this.selectedElement,
|
||||
})
|
||||
selectedElement: this.selectedElement
|
||||
|
||||
}
|
||||
if (flayer.layerDef.id === "search") {
|
||||
options.onClick = (feature) => {
|
||||
this.searchState.clickedOnMap(feature)
|
||||
}
|
||||
delete options.selectedElement
|
||||
}
|
||||
new ShowDataLayer(this.map, options)
|
||||
})
|
||||
const summaryLayerConfig = new LayerConfig(<LayerConfigJson>summaryLayer, "summaryLayer")
|
||||
new ShowDataLayer(this.map, {
|
||||
features: specialLayers.summary,
|
||||
layer: summaryLayerConfig,
|
||||
// doShowLayer: this.mapProperties.zoom.map((z) => z < maxzoom),
|
||||
selectedElement: this.selectedElement,
|
||||
selectedElement: this.selectedElement
|
||||
})
|
||||
|
||||
const lastClickLayerConfig = new LayerConfig(
|
||||
|
@ -856,14 +867,14 @@ export default class ThemeViewState implements SpecialVisualizationState {
|
|||
lastClickLayerConfig.isShown === undefined
|
||||
? specialLayers.last_click
|
||||
: specialLayers.last_click.features.mapD((fs) =>
|
||||
fs.filter((f) => {
|
||||
const matches = lastClickLayerConfig.isShown.matchesProperties(
|
||||
f.properties
|
||||
)
|
||||
console.debug("LastClick ", f, "matches", matches)
|
||||
return matches
|
||||
})
|
||||
)
|
||||
fs.filter((f) => {
|
||||
const matches = lastClickLayerConfig.isShown.matchesProperties(
|
||||
f.properties
|
||||
)
|
||||
console.debug("LastClick ", f, "matches", matches)
|
||||
return matches
|
||||
})
|
||||
)
|
||||
new ShowDataLayer(this.map, {
|
||||
features: new StaticFeatureSource(lastClickFiltered),
|
||||
layer: lastClickLayerConfig,
|
||||
|
@ -874,9 +885,9 @@ export default class ThemeViewState implements SpecialVisualizationState {
|
|||
}
|
||||
this.map.data.flyTo({
|
||||
zoom: Constants.minZoomLevelToAddNewPoint,
|
||||
center: GeoOperations.centerpointCoordinates(feature),
|
||||
center: GeoOperations.centerpointCoordinates(feature)
|
||||
})
|
||||
},
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -901,15 +912,24 @@ export default class ThemeViewState implements SpecialVisualizationState {
|
|||
})
|
||||
})
|
||||
|
||||
// Add the selected element to the recently visited history
|
||||
this.selectedElement.addCallbackD(selected => {
|
||||
const [osm_type, osm_id] = selected.properties.id.split("/")
|
||||
const [lon, lat] = GeoOperations.centerpointCoordinates(selected)
|
||||
const [lon, lat] = GeoOperations.centerpointCoordinates(selected)
|
||||
const layer = this.layout.getMatchingLayer(selected.properties)
|
||||
const r = <GeocodeResult> {
|
||||
|
||||
const nameOptions = [
|
||||
selected?.properties?.name,
|
||||
selected?.properties?.alt_name, selected?.properties?.local_name,
|
||||
layer?.title.GetRenderValue(selected?.properties ?? {}).txt,
|
||||
selected.properties.display_name,
|
||||
selected.properties.id
|
||||
]
|
||||
const r = <GeocodeResult>{
|
||||
feature: selected,
|
||||
display_name: selected.properties.name ?? selected.properties.alt_name ?? selected.properties.local_name ?? layer.title.GetRenderValue(selected.properties ?? {}).txt ,
|
||||
display_name: nameOptions.find(opt => opt !== undefined),
|
||||
osm_id, osm_type,
|
||||
lon, lat,
|
||||
lon, lat
|
||||
}
|
||||
this.userRelatedState.recentlyVisitedSearch.add(r)
|
||||
})
|
||||
|
@ -937,7 +957,7 @@ export default class ThemeViewState implements SpecialVisualizationState {
|
|||
/**
|
||||
* Searches the appropriate layer - will first try if a special layer matches; if not, a normal layer will be used by delegating to the layout
|
||||
*/
|
||||
public getMatchingLayer(properties: Record<string, string>){
|
||||
public getMatchingLayer(properties: Record<string, string>) {
|
||||
|
||||
const id = properties.id
|
||||
|
||||
|
@ -961,8 +981,8 @@ export default class ThemeViewState implements SpecialVisualizationState {
|
|||
return this.layout.getMatchingLayer(properties)
|
||||
}
|
||||
|
||||
public async reportError(message: string | Error | XMLHttpRequest, extramessage:string = "") {
|
||||
if(Utils.runningFromConsole){
|
||||
public async reportError(message: string | Error | XMLHttpRequest, extramessage: string = "") {
|
||||
if (Utils.runningFromConsole) {
|
||||
console.error("Got (in themeViewSTate.reportError):", message, extramessage)
|
||||
return
|
||||
}
|
||||
|
@ -1014,8 +1034,8 @@ export default class ThemeViewState implements SpecialVisualizationState {
|
|||
userid: this.osmConnection.userDetails.data?.uid,
|
||||
pendingChanges: this.changes.pendingChanges.data,
|
||||
previousChanges: this.changes.allChanges.data,
|
||||
changeRewrites: Utils.MapToObj(this.changes._changesetHandler._remappings),
|
||||
}),
|
||||
changeRewrites: Utils.MapToObj(this.changes._changesetHandler._remappings)
|
||||
})
|
||||
})
|
||||
} catch (e) {
|
||||
console.error("Could not upload an error report")
|
||||
|
|
|
@ -36,6 +36,7 @@
|
|||
activeFilter.control.setData(undefined)
|
||||
}
|
||||
loading = false
|
||||
state.searchState.closeIfFullscreen()
|
||||
})
|
||||
}
|
||||
</script>
|
||||
|
|
|
@ -6,21 +6,30 @@
|
|||
import ToSvelte from "../Base/ToSvelte.svelte"
|
||||
import type { FilterSearchResult } from "../../Logic/Search/FilterSearch"
|
||||
import LayerConfig from "../../Models/ThemeConfig/LayerConfig"
|
||||
import Loading from "../Base/Loading.svelte"
|
||||
|
||||
export let entry: FilterSearchResult | LayerConfig
|
||||
let isLayer = entry instanceof LayerConfig
|
||||
let asLayer = <LayerConfig> entry
|
||||
let asFilter = <FilterSearchResult> entry
|
||||
let asLayer = <LayerConfig>entry
|
||||
let asFilter = <FilterSearchResult>entry
|
||||
export let state: SpecialVisualizationState
|
||||
let dispatch = createEventDispatcher<{ select }>()
|
||||
|
||||
let loading = false
|
||||
|
||||
function apply() {
|
||||
loading = true
|
||||
console.log("Loading is now ", loading)
|
||||
window.requestAnimationFrame(() => {
|
||||
state.searchState.apply(entry)
|
||||
dispatch("select")
|
||||
loading = false
|
||||
state.searchState.closeIfFullscreen()
|
||||
})
|
||||
}
|
||||
</script>
|
||||
<button on:click={() => apply()}>
|
||||
<button on:click={() => apply()} class:disabled={loading}>
|
||||
{#if loading}
|
||||
<Loading />
|
||||
{/if}
|
||||
<div class="flex flex-col items-start">
|
||||
<div class="flex items-center gap-x-1">
|
||||
{#if isLayer}
|
||||
|
|
|
@ -48,7 +48,7 @@
|
|||
state.selectedElement.set(entry.feature)
|
||||
}
|
||||
state.userRelatedState.recentlyVisitedSearch.add(entry)
|
||||
dispatch("select")
|
||||
state.searchState.closeIfFullscreen()
|
||||
}
|
||||
</script>
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue