forked from MapComplete/MapComplete
Refactoring: Load availableMVTVectorLayers dynamically
This commit is contained in:
parent
2b3e3257fd
commit
a50c6b531e
14 changed files with 115 additions and 68 deletions
|
@ -1,6 +1,6 @@
|
||||||
import GeoJsonSource from "./GeoJsonSource"
|
import GeoJsonSource from "./GeoJsonSource"
|
||||||
import LayerConfig from "../../../Models/ThemeConfig/LayerConfig"
|
import LayerConfig from "../../../Models/ThemeConfig/LayerConfig"
|
||||||
import { FeatureSource, UpdatableFeatureSource } from "../FeatureSource"
|
import { FeatureSource, IndexedFeatureSource, UpdatableFeatureSource } from "../FeatureSource"
|
||||||
import { Or } from "../../Tags/Or"
|
import { Or } from "../../Tags/Or"
|
||||||
import FeatureSwitchState from "../../State/FeatureSwitchState"
|
import FeatureSwitchState from "../../State/FeatureSwitchState"
|
||||||
import OverpassFeatureSource from "./OverpassFeatureSource"
|
import OverpassFeatureSource from "./OverpassFeatureSource"
|
||||||
|
@ -12,13 +12,15 @@ import LocalStorageFeatureSource from "../TiledFeatureSource/LocalStorageFeature
|
||||||
import FullNodeDatabaseSource from "../TiledFeatureSource/FullNodeDatabaseSource"
|
import FullNodeDatabaseSource from "../TiledFeatureSource/FullNodeDatabaseSource"
|
||||||
import DynamicMvtileSource from "../TiledFeatureSource/DynamicMvtTileSource"
|
import DynamicMvtileSource from "../TiledFeatureSource/DynamicMvtTileSource"
|
||||||
import FeatureSourceMerger from "./FeatureSourceMerger"
|
import FeatureSourceMerger from "./FeatureSourceMerger"
|
||||||
|
import { Feature } from "geojson"
|
||||||
|
import { OsmFeature } from "../../../Models/OsmFeature"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This source will fetch the needed data from various sources for the given layout.
|
* This source will fetch the needed data from various sources for the given layout.
|
||||||
*
|
*
|
||||||
* Note that special layers (with `source=null` will be ignored)
|
* Note that special layers (with `source=null` will be ignored)
|
||||||
*/
|
*/
|
||||||
export default class ThemeSource extends FeatureSourceMerger {
|
export default class ThemeSource implements IndexedFeatureSource {
|
||||||
/**
|
/**
|
||||||
* Indicates if a data source is loading something
|
* Indicates if a data source is loading something
|
||||||
*/
|
*/
|
||||||
|
@ -26,6 +28,61 @@ export default class ThemeSource extends FeatureSourceMerger {
|
||||||
|
|
||||||
public static readonly fromCacheZoomLevel = 15
|
public static readonly fromCacheZoomLevel = 15
|
||||||
|
|
||||||
|
public features: UIEventSource<Feature[]> = new UIEventSource([])
|
||||||
|
public readonly featuresById: Store<Map<string, Feature>>
|
||||||
|
private readonly core: Store<ThemeSourceCore>
|
||||||
|
|
||||||
|
|
||||||
|
private readonly addedSources: FeatureSource[] = []
|
||||||
|
private readonly addedItems: OsmFeature[] = []
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
layers: LayerConfig[],
|
||||||
|
featureSwitches: FeatureSwitchState,
|
||||||
|
mapProperties: { bounds: Store<BBox>; zoom: Store<number> },
|
||||||
|
backend: string,
|
||||||
|
isDisplayed: (id: string) => Store<boolean>,
|
||||||
|
mvtAvailableLayers: Store<Set<string>>,
|
||||||
|
fullNodeDatabaseSource?: FullNodeDatabaseSource
|
||||||
|
) {
|
||||||
|
const isLoading = new UIEventSource(true)
|
||||||
|
this.isLoading = isLoading
|
||||||
|
|
||||||
|
const features = this.features = new UIEventSource<Feature[]>([])
|
||||||
|
const featuresById = this.featuresById = new UIEventSource(new Map())
|
||||||
|
this.core = mvtAvailableLayers.mapD(mvtAvailableLayers => {
|
||||||
|
const core = new ThemeSourceCore(layers, featureSwitches, mapProperties, backend, isDisplayed, mvtAvailableLayers, isLoading, fullNodeDatabaseSource)
|
||||||
|
this.addedSources.forEach(src => core.addSource(src))
|
||||||
|
this.addedItems.forEach(item => core.addItem(item))
|
||||||
|
core.features.addCallbackAndRun(data => features.set(data))
|
||||||
|
core.featuresById.addCallbackAndRun(data => featuresById.set(data))
|
||||||
|
return core
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
public async downloadAll() {
|
||||||
|
return this.core.data.downloadAll()
|
||||||
|
}
|
||||||
|
|
||||||
|
public addSource(source: FeatureSource) {
|
||||||
|
this.core.data?.addSource(source)
|
||||||
|
this.addedSources.push(source)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public addItem(obj: OsmFeature) {
|
||||||
|
this.core.data?.addItem(obj)
|
||||||
|
this.addedItems.push(obj)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This source will fetch the needed data from various sources for the given layout.
|
||||||
|
*
|
||||||
|
* Note that special layers (with `source=null` will be ignored)
|
||||||
|
*/
|
||||||
|
class ThemeSourceCore extends FeatureSourceMerger {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This source is _only_ triggered when the data is downloaded for CSV export
|
* This source is _only_ triggered when the data is downloaded for CSV export
|
||||||
* @private
|
* @private
|
||||||
|
@ -40,6 +97,7 @@ export default class ThemeSource extends FeatureSourceMerger {
|
||||||
backend: string,
|
backend: string,
|
||||||
isDisplayed: (id: string) => Store<boolean>,
|
isDisplayed: (id: string) => Store<boolean>,
|
||||||
mvtAvailableLayers: Set<string>,
|
mvtAvailableLayers: Set<string>,
|
||||||
|
isLoading: UIEventSource<boolean>,
|
||||||
fullNodeDatabaseSource?: FullNodeDatabaseSource
|
fullNodeDatabaseSource?: FullNodeDatabaseSource
|
||||||
) {
|
) {
|
||||||
const { bounds, zoom } = mapProperties
|
const { bounds, zoom } = mapProperties
|
||||||
|
@ -58,7 +116,7 @@ export default class ThemeSource extends FeatureSourceMerger {
|
||||||
mapProperties,
|
mapProperties,
|
||||||
{
|
{
|
||||||
isActive: isDisplayed(layer.id),
|
isActive: isDisplayed(layer.id),
|
||||||
maxAge: layer.maxAgeOfCache,
|
maxAge: layer.maxAgeOfCache
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
fromCache.set(layer.id, src)
|
fromCache.set(layer.id, src)
|
||||||
|
@ -66,13 +124,11 @@ export default class ThemeSource extends FeatureSourceMerger {
|
||||||
}
|
}
|
||||||
const mvtSources: UpdatableFeatureSource[] = osmLayers
|
const mvtSources: UpdatableFeatureSource[] = osmLayers
|
||||||
.filter((f) => mvtAvailableLayers.has(f.id))
|
.filter((f) => mvtAvailableLayers.has(f.id))
|
||||||
.map((l) => ThemeSource.setupMvtSource(l, mapProperties, isDisplayed(l.id)))
|
.map((l) => ThemeSourceCore.setupMvtSource(l, mapProperties, isDisplayed(l.id)))
|
||||||
const nonMvtSources: FeatureSource[] = []
|
const nonMvtSources: FeatureSource[] = []
|
||||||
const nonMvtLayers: LayerConfig[] = osmLayers.filter((l) => !mvtAvailableLayers.has(l.id))
|
const nonMvtLayers: LayerConfig[] = osmLayers.filter((l) => !mvtAvailableLayers.has(l.id))
|
||||||
|
|
||||||
const isLoading = new UIEventSource(false)
|
const osmApiSource = ThemeSourceCore.setupOsmApiSource(
|
||||||
|
|
||||||
const osmApiSource = ThemeSource.setupOsmApiSource(
|
|
||||||
osmLayers,
|
osmLayers,
|
||||||
bounds,
|
bounds,
|
||||||
zoom,
|
zoom,
|
||||||
|
@ -89,7 +145,7 @@ export default class ThemeSource extends FeatureSourceMerger {
|
||||||
nonMvtLayers.map((l) => l.id),
|
nonMvtLayers.map((l) => l.id),
|
||||||
" cannot be fetched from the cache server, defaulting to overpass/OSM-api"
|
" cannot be fetched from the cache server, defaulting to overpass/OSM-api"
|
||||||
)
|
)
|
||||||
overpassSource = ThemeSource.setupOverpass(osmLayers, bounds, zoom, featureSwitches)
|
overpassSource = ThemeSourceCore.setupOverpass(osmLayers, bounds, zoom, featureSwitches)
|
||||||
nonMvtSources.push(overpassSource)
|
nonMvtSources.push(overpassSource)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -102,7 +158,7 @@ export default class ThemeSource extends FeatureSourceMerger {
|
||||||
osmApiSource?.isRunning?.addCallbackAndRun(() => setIsLoading())
|
osmApiSource?.isRunning?.addCallbackAndRun(() => setIsLoading())
|
||||||
|
|
||||||
const geojsonSources: UpdatableFeatureSource[] = geojsonlayers.map((l) =>
|
const geojsonSources: UpdatableFeatureSource[] = geojsonlayers.map((l) =>
|
||||||
ThemeSource.setupGeojsonSource(l, mapProperties, isDisplayed(l.id))
|
ThemeSourceCore.setupGeojsonSource(l, mapProperties, isDisplayed(l.id))
|
||||||
)
|
)
|
||||||
|
|
||||||
const downloadAll = new OverpassFeatureSource(
|
const downloadAll = new OverpassFeatureSource(
|
||||||
|
@ -113,11 +169,11 @@ export default class ThemeSource extends FeatureSourceMerger {
|
||||||
overpassUrl: featureSwitches.overpassUrl,
|
overpassUrl: featureSwitches.overpassUrl,
|
||||||
overpassTimeout: featureSwitches.overpassTimeout,
|
overpassTimeout: featureSwitches.overpassTimeout,
|
||||||
overpassMaxZoom: new ImmutableStore(99),
|
overpassMaxZoom: new ImmutableStore(99),
|
||||||
widenFactor: 0,
|
widenFactor: 0
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
ignoreZoom: true,
|
ignoreZoom: true,
|
||||||
isActive: new ImmutableStore(false),
|
isActive: new ImmutableStore(false)
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -129,7 +185,6 @@ export default class ThemeSource extends FeatureSourceMerger {
|
||||||
downloadAll
|
downloadAll
|
||||||
)
|
)
|
||||||
|
|
||||||
this.isLoading = isLoading
|
|
||||||
this._downloadAll = downloadAll
|
this._downloadAll = downloadAll
|
||||||
this._mapBounds = mapProperties.bounds
|
this._mapBounds = mapProperties.bounds
|
||||||
}
|
}
|
||||||
|
@ -192,7 +247,7 @@ export default class ThemeSource extends FeatureSourceMerger {
|
||||||
backend,
|
backend,
|
||||||
isActive,
|
isActive,
|
||||||
patchRelations: true,
|
patchRelations: true,
|
||||||
fullNodeDatabase,
|
fullNodeDatabase
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -224,11 +279,11 @@ export default class ThemeSource extends FeatureSourceMerger {
|
||||||
widenFactor: 1.5,
|
widenFactor: 1.5,
|
||||||
overpassUrl: featureSwitches.overpassUrl,
|
overpassUrl: featureSwitches.overpassUrl,
|
||||||
overpassTimeout: featureSwitches.overpassTimeout,
|
overpassTimeout: featureSwitches.overpassTimeout,
|
||||||
overpassMaxZoom: featureSwitches.overpassMaxZoom,
|
overpassMaxZoom: featureSwitches.overpassMaxZoom
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
padToTiles: zoom.map((zoom) => Math.min(15, zoom + 1)),
|
padToTiles: zoom.map((zoom) => Math.min(15, zoom + 1)),
|
||||||
isActive,
|
isActive
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,8 +8,7 @@ export default class ThemeViewStateHashActor {
|
||||||
private readonly _state: {
|
private readonly _state: {
|
||||||
indexedFeatures: IndexedFeatureSource,
|
indexedFeatures: IndexedFeatureSource,
|
||||||
selectedElement: UIEventSource<Feature>,
|
selectedElement: UIEventSource<Feature>,
|
||||||
guistate: MenuState,
|
guistate: MenuState
|
||||||
previewedImage: UIEventSource<object>
|
|
||||||
}
|
}
|
||||||
private isUpdatingHash = false
|
private isUpdatingHash = false
|
||||||
|
|
||||||
|
@ -39,7 +38,6 @@ export default class ThemeViewStateHashActor {
|
||||||
indexedFeatures: IndexedFeatureSource,
|
indexedFeatures: IndexedFeatureSource,
|
||||||
selectedElement: UIEventSource<Feature>,
|
selectedElement: UIEventSource<Feature>,
|
||||||
guistate: MenuState,
|
guistate: MenuState,
|
||||||
previewedImage: UIEventSource<object>
|
|
||||||
}) {
|
}) {
|
||||||
this._state = state
|
this._state = state
|
||||||
|
|
||||||
|
@ -150,14 +148,8 @@ export default class ThemeViewStateHashActor {
|
||||||
}
|
}
|
||||||
|
|
||||||
private back() {
|
private back() {
|
||||||
|
console.log("Going back via hash actor")
|
||||||
const state = this._state
|
const state = this._state
|
||||||
if (state.previewedImage.data) {
|
state.guistate.closeAll()
|
||||||
state.previewedImage.setData(undefined)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if (state.guistate.closeAll()) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
state.selectedElement.setData(undefined)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
import ThemeConfig from "./ThemeConfig/ThemeConfig"
|
import ThemeConfig from "./ThemeConfig/ThemeConfig"
|
||||||
import { WithImageState } from "./ThemeViewState/WithImageState"
|
import { WithImageState } from "./ThemeViewState/WithImageState"
|
||||||
|
import { Store } from "../Logic/UIEventSource"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
|
@ -10,7 +11,7 @@ import { WithImageState } from "./ThemeViewState/WithImageState"
|
||||||
* It ties up all the needed elements and starts some actors.
|
* It ties up all the needed elements and starts some actors.
|
||||||
*/
|
*/
|
||||||
export default class ThemeViewState extends WithImageState {
|
export default class ThemeViewState extends WithImageState {
|
||||||
constructor(layout: ThemeConfig, mvtAvailableLayers: Set<string>) {
|
constructor(layout: ThemeConfig, mvtAvailableLayers: Store<Set<string>>) {
|
||||||
super(layout, mvtAvailableLayers)
|
super(layout, mvtAvailableLayers)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -35,7 +35,7 @@ export class WithChangesState extends WithLayoutSourceState {
|
||||||
*/
|
*/
|
||||||
readonly hasDataInView: Store<FeatureViewState>
|
readonly hasDataInView: Store<FeatureViewState>
|
||||||
|
|
||||||
constructor(theme: ThemeConfig, mvtAvailableLayers: Set<string>) {
|
constructor(theme: ThemeConfig, mvtAvailableLayers: Store<Set<string>>) {
|
||||||
super(theme, mvtAvailableLayers)
|
super(theme, mvtAvailableLayers)
|
||||||
this.changes = new Changes(
|
this.changes = new Changes(
|
||||||
{
|
{
|
||||||
|
|
|
@ -3,6 +3,7 @@ import { MenuState } from "../MenuState"
|
||||||
import Hotkeys from "../../UI/Base/Hotkeys"
|
import Hotkeys from "../../UI/Base/Hotkeys"
|
||||||
import Translations from "../../UI/i18n/Translations"
|
import Translations from "../../UI/i18n/Translations"
|
||||||
import { WithSpecialLayers } from "./WithSpecialLayers"
|
import { WithSpecialLayers } from "./WithSpecialLayers"
|
||||||
|
import { Store } from "../../Logic/UIEventSource"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Does all things related to:
|
* Does all things related to:
|
||||||
|
@ -11,9 +12,10 @@ import { WithSpecialLayers } from "./WithSpecialLayers"
|
||||||
export class WithGuiState extends WithSpecialLayers {
|
export class WithGuiState extends WithSpecialLayers {
|
||||||
readonly guistate: MenuState
|
readonly guistate: MenuState
|
||||||
|
|
||||||
constructor(theme: ThemeConfig, mvtAvailableLayers: Set<string>) {
|
constructor(theme: ThemeConfig, mvtAvailableLayers: Store<Set<string>>) {
|
||||||
super(theme, mvtAvailableLayers)
|
super(theme, mvtAvailableLayers)
|
||||||
this.guistate = new MenuState(
|
this.guistate = new MenuState(this.selectedElement)
|
||||||
|
this.guistate.openMenuIfNeeded(
|
||||||
this.featureSwitches.featureSwitchWelcomeMessage.data,
|
this.featureSwitches.featureSwitchWelcomeMessage.data,
|
||||||
theme.id
|
theme.id
|
||||||
)
|
)
|
||||||
|
|
|
@ -22,7 +22,7 @@ export class WithLayoutSourceState extends WithSelectedElementState {
|
||||||
readonly floors: Store<string[]>
|
readonly floors: Store<string[]>
|
||||||
|
|
||||||
|
|
||||||
constructor(theme: ThemeConfig, mvtAvailableLayers: Set<string>) {
|
constructor(theme: ThemeConfig, mvtAvailableLayers: Store<Set<string>>) {
|
||||||
super(theme)
|
super(theme)
|
||||||
/* Set up the layout source
|
/* Set up the layout source
|
||||||
* A bit tricky, as this is heavily intertwined with the 'changes'-element, which generates a stream of new and changed features too
|
* A bit tricky, as this is heavily intertwined with the 'changes'-element, which generates a stream of new and changed features too
|
||||||
|
|
|
@ -7,11 +7,12 @@ import { WithVisualFeedbackState } from "./WithVisualFeedbackState"
|
||||||
import { ShowDataLayerOptions } from "../../UI/Map/ShowDataLayerOptions"
|
import { ShowDataLayerOptions } from "../../UI/Map/ShowDataLayerOptions"
|
||||||
import LayerConfig from "../ThemeConfig/LayerConfig"
|
import LayerConfig from "../ThemeConfig/LayerConfig"
|
||||||
import ShowDataLayer from "../../UI/Map/ShowDataLayer"
|
import ShowDataLayer from "../../UI/Map/ShowDataLayer"
|
||||||
|
import { Store } from "../../Logic/UIEventSource"
|
||||||
|
|
||||||
export class WithSearchState extends WithVisualFeedbackState {
|
export class WithSearchState extends WithVisualFeedbackState {
|
||||||
public readonly searchState: SearchState
|
public readonly searchState: SearchState
|
||||||
|
|
||||||
constructor(theme: ThemeConfig, mvtAvailableLayers: Set<string>) {
|
constructor(theme: ThemeConfig, mvtAvailableLayers: Store<Set<string>>) {
|
||||||
super(theme, mvtAvailableLayers)
|
super(theme, mvtAvailableLayers)
|
||||||
this.searchState = new SearchState(this)
|
this.searchState = new SearchState(this)
|
||||||
this.initHotkeysSearch()
|
this.initHotkeysSearch()
|
||||||
|
@ -48,20 +49,12 @@ export class WithSearchState extends WithVisualFeedbackState {
|
||||||
)
|
)
|
||||||
|
|
||||||
Hotkeys.RegisterHotkey({ nomod: "Escape", onUp: true }, docs.closeSidebar, () => {
|
Hotkeys.RegisterHotkey({ nomod: "Escape", onUp: true }, docs.closeSidebar, () => {
|
||||||
if (this.previewedImage.data !== undefined) {
|
|
||||||
this.previewedImage.setData(undefined)
|
if (this.guistate.closeAll()) {
|
||||||
return
|
|
||||||
}
|
|
||||||
if (this.selectedElement.data) {
|
|
||||||
this.selectedElement.setData(undefined)
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if (this.searchState.showSearchDrawer.data) {
|
if (this.searchState.showSearchDrawer.data) {
|
||||||
this.searchState.showSearchDrawer.set(false)
|
this.searchState.showSearchDrawer.set(false)
|
||||||
return
|
|
||||||
}
|
|
||||||
if (this.guistate.closeAll()) {
|
|
||||||
return
|
|
||||||
}
|
}
|
||||||
Zoomcontrol.resetzoom()
|
Zoomcontrol.resetzoom()
|
||||||
this.focusOnMap()
|
this.focusOnMap()
|
||||||
|
|
|
@ -28,11 +28,10 @@ export class WithSelectedElementState extends UserMapFeatureswitchState {
|
||||||
})
|
})
|
||||||
|
|
||||||
this.mapProperties.lastClickLocation.addCallbackD((lastClick) => {
|
this.mapProperties.lastClickLocation.addCallbackD((lastClick) => {
|
||||||
if (lastClick.mode !== "left" || !lastClick.nearestFeature) {
|
if (lastClick.mode !== "left") {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
const f = lastClick.nearestFeature
|
this.setSelectedElement(lastClick.nearestFeature)
|
||||||
this.setSelectedElement(f)
|
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
||||||
|
@ -67,7 +66,7 @@ export class WithSelectedElementState extends UserMapFeatureswitchState {
|
||||||
const current = this.selectedElement.data
|
const current = this.selectedElement.data
|
||||||
if (
|
if (
|
||||||
current?.properties?.id !== undefined &&
|
current?.properties?.id !== undefined &&
|
||||||
current.properties.id === feature.properties.id
|
current.properties.id === feature?.properties?.id
|
||||||
) {
|
) {
|
||||||
console.log("Not setting selected, same id", current, feature)
|
console.log("Not setting selected, same id", current, feature)
|
||||||
return // already set
|
return // already set
|
||||||
|
|
|
@ -14,7 +14,7 @@ import { LayerConfigJson } from "../ThemeConfig/Json/LayerConfigJson"
|
||||||
import last_click_layerconfig from "../../assets/generated/layers/last_click.json"
|
import last_click_layerconfig from "../../assets/generated/layers/last_click.json"
|
||||||
import { GeoOperations } from "../../Logic/GeoOperations"
|
import { GeoOperations } from "../../Logic/GeoOperations"
|
||||||
import summaryLayer from "../../assets/generated/layers/summary.json"
|
import summaryLayer from "../../assets/generated/layers/summary.json"
|
||||||
import { UIEventSource } from "../../Logic/UIEventSource"
|
import { Store, UIEventSource } from "../../Logic/UIEventSource"
|
||||||
import NearbyFeatureSource from "../../Logic/FeatureSource/Sources/NearbyFeatureSource"
|
import NearbyFeatureSource from "../../Logic/FeatureSource/Sources/NearbyFeatureSource"
|
||||||
import {
|
import {
|
||||||
SummaryTileSource,
|
SummaryTileSource,
|
||||||
|
@ -43,7 +43,7 @@ export class WithSpecialLayers extends WithChangesState {
|
||||||
readonly visualFeedbackViewportBounds: UIEventSource<BBox> = new UIEventSource<BBox>(undefined)
|
readonly visualFeedbackViewportBounds: UIEventSource<BBox> = new UIEventSource<BBox>(undefined)
|
||||||
|
|
||||||
|
|
||||||
constructor(theme: ThemeConfig, mvtAvailableLayers: Set<string>) {
|
constructor(theme: ThemeConfig, mvtAvailableLayers: Store<Set<string>>) {
|
||||||
super(theme, mvtAvailableLayers)
|
super(theme, mvtAvailableLayers)
|
||||||
|
|
||||||
this.favourites = new FavouritesFeatureSource(this)
|
this.favourites = new FavouritesFeatureSource(this)
|
||||||
|
@ -64,12 +64,12 @@ export class WithSpecialLayers extends WithChangesState {
|
||||||
|
|
||||||
this.featureSummary = this.setupSummaryLayer()
|
this.featureSummary = this.setupSummaryLayer()
|
||||||
this.initActorsSpecialLayers()
|
this.initActorsSpecialLayers()
|
||||||
|
this.drawSelectedElement()
|
||||||
this.drawSpecialLayers()
|
this.drawSpecialLayers()
|
||||||
this.drawLastClick()
|
this.drawLastClick()
|
||||||
// Note: the lock-range is handled by UserMapFeatureSwitchState
|
// Note: the lock-range is handled by UserMapFeatureSwitchState
|
||||||
{
|
{
|
||||||
// Activate metatagging for the 'current_view' layer
|
// Activate metatagging for the 'current_view' layer
|
||||||
console.log(">>>", this.layerState.filteredLayers)
|
|
||||||
const currentViewLayer = this.layerState.filteredLayers.get("current_view")?.layerDef
|
const currentViewLayer = this.layerState.filteredLayers.get("current_view")?.layerDef
|
||||||
if (currentViewLayer?.tagRenderings?.length > 0) {
|
if (currentViewLayer?.tagRenderings?.length > 0) {
|
||||||
const params = MetaTagging.createExtraFuncParams(this)
|
const params = MetaTagging.createExtraFuncParams(this)
|
||||||
|
@ -163,8 +163,10 @@ export class WithSpecialLayers extends WithChangesState {
|
||||||
})
|
})
|
||||||
)
|
)
|
||||||
// show last click = new point/note marker
|
// show last click = new point/note marker
|
||||||
|
const features = new StaticFeatureSource(lastClickFiltered)
|
||||||
|
this.featureProperties.trackFeatureSource(features)
|
||||||
new ShowDataLayer(this.map, {
|
new ShowDataLayer(this.map, {
|
||||||
features: new StaticFeatureSource(lastClickFiltered),
|
features,
|
||||||
layer: lastClickLayerConfig,
|
layer: lastClickLayerConfig,
|
||||||
onClick: (feature) => {
|
onClick: (feature) => {
|
||||||
if (this.mapProperties.zoom.data >= Constants.minZoomLevelToAddNewPoint) {
|
if (this.mapProperties.zoom.data >= Constants.minZoomLevelToAddNewPoint) {
|
||||||
|
@ -179,6 +181,13 @@ export class WithSpecialLayers extends WithChangesState {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private drawSelectedElement() {
|
||||||
|
const src = new StaticFeatureSource(
|
||||||
|
this.selectedElement.map((f) => (f === undefined ? [] : [f]))
|
||||||
|
)
|
||||||
|
ShowDataLayer.showMultipleLayers(this.map, src, this.theme.layers)
|
||||||
|
}
|
||||||
|
|
||||||
private drawSpecialLayers() {
|
private drawSpecialLayers() {
|
||||||
|
|
||||||
type AddedByDefaultTypes = (typeof Constants.added_by_default)[number]
|
type AddedByDefaultTypes = (typeof Constants.added_by_default)[number]
|
||||||
|
@ -187,6 +196,7 @@ export class WithSpecialLayers extends WithChangesState {
|
||||||
| "last_click" // handled by this.drawLastClick()
|
| "last_click" // handled by this.drawLastClick()
|
||||||
| "summary" // handled by setupSummaryLayer
|
| "summary" // handled by setupSummaryLayer
|
||||||
| "range" // handled by UserMapFeatureSwitchState
|
| "range" // handled by UserMapFeatureSwitchState
|
||||||
|
| "selected_element" // handled by this.drawSelectedElement
|
||||||
>
|
>
|
||||||
const empty = []
|
const empty = []
|
||||||
/**
|
/**
|
||||||
|
@ -199,10 +209,7 @@ export class WithSpecialLayers extends WithChangesState {
|
||||||
gps_track: this.geolocation.historicalUserLocationsTrack,
|
gps_track: this.geolocation.historicalUserLocationsTrack,
|
||||||
current_view: this.currentView,
|
current_view: this.currentView,
|
||||||
favourite: this.favourites,
|
favourite: this.favourites,
|
||||||
geocoded_image: new StaticFeatureSource(this.geocodedImages),
|
geocoded_image: new StaticFeatureSource(this.geocodedImages)
|
||||||
selected_element: new StaticFeatureSource(
|
|
||||||
this.selectedElement.map((f) => (f === undefined ? empty : [f]))
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import ThemeConfig from "../ThemeConfig/ThemeConfig"
|
import ThemeConfig from "../ThemeConfig/ThemeConfig"
|
||||||
import { UIEventSource } from "../../Logic/UIEventSource"
|
import { Store, UIEventSource } from "../../Logic/UIEventSource"
|
||||||
import Hotkeys from "../../UI/Base/Hotkeys"
|
import Hotkeys from "../../UI/Base/Hotkeys"
|
||||||
import Translations from "../../UI/i18n/Translations"
|
import Translations from "../../UI/i18n/Translations"
|
||||||
import ThemeViewState from "../ThemeViewState"
|
import ThemeViewState from "../ThemeViewState"
|
||||||
|
@ -11,7 +11,7 @@ export class WithVisualFeedbackState extends ThemeViewState {
|
||||||
*/
|
*/
|
||||||
public readonly visualFeedback: UIEventSource<boolean> = new UIEventSource<boolean>(false)
|
public readonly visualFeedback: UIEventSource<boolean> = new UIEventSource<boolean>(false)
|
||||||
|
|
||||||
constructor(theme: ThemeConfig, mvtAvailableLayers: Set<string>) {
|
constructor(theme: ThemeConfig, mvtAvailableLayers: Store<Set<string>>) {
|
||||||
super(theme, mvtAvailableLayers)
|
super(theme, mvtAvailableLayers)
|
||||||
this.initHotkeysVisualFeedback()
|
this.initHotkeysVisualFeedback()
|
||||||
|
|
||||||
|
@ -72,7 +72,7 @@ export class WithVisualFeedbackState extends ThemeViewState {
|
||||||
if (this.selectedElement.data !== undefined) {
|
if (this.selectedElement.data !== undefined) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
if (this.guistate.isSomethingOpen() || this.previewedImage.data !== undefined) {
|
if (this.guistate.isSomethingOpen()) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if (
|
if (
|
||||||
|
|
|
@ -9,7 +9,7 @@
|
||||||
export let fullscreen: boolean = false
|
export let fullscreen: boolean = false
|
||||||
export let bodyPadding = "p-4 md:p-5 "
|
export let bodyPadding = "p-4 md:p-5 "
|
||||||
export let shown: UIEventSource<boolean>
|
export let shown: UIEventSource<boolean>
|
||||||
export let dismissable = true
|
export let dismissable = false
|
||||||
/**
|
/**
|
||||||
* Default: 50
|
* Default: 50
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -16,7 +16,6 @@ import PerLayerFeatureSourceSplitter from "../../Logic/FeatureSource/PerLayerFea
|
||||||
import FilteredLayer from "../../Models/FilteredLayer"
|
import FilteredLayer from "../../Models/FilteredLayer"
|
||||||
import SimpleFeatureSource from "../../Logic/FeatureSource/Sources/SimpleFeatureSource"
|
import SimpleFeatureSource from "../../Logic/FeatureSource/Sources/SimpleFeatureSource"
|
||||||
import { TagsFilter } from "../../Logic/Tags/TagsFilter"
|
import { TagsFilter } from "../../Logic/Tags/TagsFilter"
|
||||||
import { featureEach } from "@turf/turf"
|
|
||||||
|
|
||||||
class PointRenderingLayer {
|
class PointRenderingLayer {
|
||||||
private readonly _config: PointRenderingConfig
|
private readonly _config: PointRenderingConfig
|
||||||
|
@ -542,7 +541,7 @@ export default class ShowDataLayer {
|
||||||
mlmap: UIEventSource<MlMap>,
|
mlmap: UIEventSource<MlMap>,
|
||||||
features: FeatureSource,
|
features: FeatureSource,
|
||||||
layers: LayerConfig[],
|
layers: LayerConfig[],
|
||||||
options?: Partial<ShowDataLayerOptions>
|
options?: Partial<Omit<ShowDataLayerOptions, "features" | "layer">>
|
||||||
) {
|
) {
|
||||||
const perLayer: PerLayerFeatureSourceSplitter<FeatureSourceForLayer> =
|
const perLayer: PerLayerFeatureSourceSplitter<FeatureSourceForLayer> =
|
||||||
new PerLayerFeatureSourceSplitter(
|
new PerLayerFeatureSourceSplitter(
|
||||||
|
|
|
@ -14,7 +14,6 @@ import FeatureSwitchState from "../Logic/State/FeatureSwitchState"
|
||||||
import OsmObjectDownloader from "../Logic/Osm/OsmObjectDownloader"
|
import OsmObjectDownloader from "../Logic/Osm/OsmObjectDownloader"
|
||||||
import { ImageUploadManager } from "../Logic/ImageProviders/ImageUploadManager"
|
import { ImageUploadManager } from "../Logic/ImageProviders/ImageUploadManager"
|
||||||
import FavouritesFeatureSource from "../Logic/FeatureSource/Sources/FavouritesFeatureSource"
|
import FavouritesFeatureSource from "../Logic/FeatureSource/Sources/FavouritesFeatureSource"
|
||||||
import { ProvidedImage } from "../Logic/ImageProviders/ImageProvider"
|
|
||||||
import GeoLocationHandler from "../Logic/Actors/GeoLocationHandler"
|
import GeoLocationHandler from "../Logic/Actors/GeoLocationHandler"
|
||||||
import ThemeSource from "../Logic/FeatureSource/Sources/ThemeSource"
|
import ThemeSource from "../Logic/FeatureSource/Sources/ThemeSource"
|
||||||
import { Map as MlMap } from "maplibre-gl"
|
import { Map as MlMap } from "maplibre-gl"
|
||||||
|
@ -71,7 +70,6 @@ export interface SpecialVisualizationState {
|
||||||
|
|
||||||
readonly imageUploadManager: ImageUploadManager
|
readonly imageUploadManager: ImageUploadManager
|
||||||
|
|
||||||
readonly previewedImage: UIEventSource<ProvidedImage>
|
|
||||||
readonly nearbyImageSearcher: CombinedFetcher
|
readonly nearbyImageSearcher: CombinedFetcher
|
||||||
readonly geolocation: GeoLocationHandler
|
readonly geolocation: GeoLocationHandler
|
||||||
readonly geocodedImages: UIEventSource<Feature[]>
|
readonly geocodedImages: UIEventSource<Feature[]>
|
||||||
|
|
|
@ -8,6 +8,7 @@ import { Utils } from "./Utils"
|
||||||
import Constants from "./Models/Constants"
|
import Constants from "./Models/Constants"
|
||||||
import ArrowDownTray from "@babeard/svelte-heroicons/mini/ArrowDownTray"
|
import ArrowDownTray from "@babeard/svelte-heroicons/mini/ArrowDownTray"
|
||||||
import { WithSearchState } from "./Models/ThemeViewState/WithSearchState"
|
import { WithSearchState } from "./Models/ThemeViewState/WithSearchState"
|
||||||
|
import { UIEventSource } from "./Logic/UIEventSource"
|
||||||
|
|
||||||
function webgl_support() {
|
function webgl_support() {
|
||||||
try {
|
try {
|
||||||
|
@ -48,11 +49,11 @@ async function main() {
|
||||||
if (!webgl_support()) {
|
if (!webgl_support()) {
|
||||||
throw "WebGL is not supported or not enabled. This is essential for MapComplete to function, please enable this."
|
throw "WebGL is not supported or not enabled. This is essential for MapComplete to function, please enable this."
|
||||||
}
|
}
|
||||||
const [theme, availableLayers] = await Promise.all([
|
const availableLayers = UIEventSource.FromPromise(getAvailableLayers())
|
||||||
DetermineTheme.getTheme(),
|
const theme = await DetermineTheme.getTheme()
|
||||||
await getAvailableLayers(),
|
availableLayers.addCallbackAndRunD(availableLayers => {
|
||||||
])
|
|
||||||
console.log("The available layers on server are", Array.from(availableLayers))
|
console.log("The available layers on server are", Array.from(availableLayers))
|
||||||
|
})
|
||||||
const state = new WithSearchState(theme, availableLayers)
|
const state = new WithSearchState(theme, availableLayers)
|
||||||
const target = document.getElementById("maindiv")
|
const target = document.getElementById("maindiv")
|
||||||
const childs = Array.from(target.children)
|
const childs = Array.from(target.children)
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue