forked from MapComplete/MapComplete
Add current view popup
This commit is contained in:
commit
c76b0a6340
9 changed files with 116 additions and 45 deletions
|
@ -152,6 +152,11 @@ export default class FeaturePipeline {
|
||||||
handlePriviligedFeatureSource(state.homeLocation)
|
handlePriviligedFeatureSource(state.homeLocation)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (id === "current_view") {
|
||||||
|
handlePriviligedFeatureSource(state.currentView)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
const localTileSaver = new SaveTileToLocalStorageActor(filteredLayer)
|
const localTileSaver = new SaveTileToLocalStorageActor(filteredLayer)
|
||||||
this.localStorageSavers.set(filteredLayer.layerDef.id, localTileSaver)
|
this.localStorageSavers.set(filteredLayer.layerDef.id, localTileSaver)
|
||||||
|
|
|
@ -45,7 +45,10 @@ export default class MapState extends UserRelatedState {
|
||||||
lon: number;
|
lon: number;
|
||||||
}> = new UIEventSource<{ lat: number; lon: number }>(undefined);
|
}> = new UIEventSource<{ lat: number; lon: number }>(undefined);
|
||||||
|
|
||||||
public currentView: FeatureSourceForLayer
|
/**
|
||||||
|
* The bounds of the current map view
|
||||||
|
*/
|
||||||
|
public currentView: FeatureSourceForLayer & Tiled;
|
||||||
/**
|
/**
|
||||||
* The location as delivered by the GPS
|
* The location as delivered by the GPS
|
||||||
*/
|
*/
|
||||||
|
@ -174,30 +177,43 @@ export default class MapState extends UserRelatedState {
|
||||||
}
|
}
|
||||||
|
|
||||||
private initCurrentView(){
|
private initCurrentView(){
|
||||||
|
let currentViewLayer: FilteredLayer = this.filteredLayers.data.filter(l => l.layerDef.id === "current_view")[0]
|
||||||
|
|
||||||
|
if(currentViewLayer === undefined){
|
||||||
|
// This layer is not needed by the theme and thus unloaded
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
let i = 0
|
||||||
const features : UIEventSource<{ feature: any, freshness: Date }[]>= this.currentBounds.map(bounds => {
|
const features : UIEventSource<{ feature: any, freshness: Date }[]>= this.currentBounds.map(bounds => {
|
||||||
|
if(bounds === undefined){
|
||||||
|
return []
|
||||||
|
}
|
||||||
|
i++
|
||||||
const feature = {
|
const feature = {
|
||||||
freshness: new Date(),
|
freshness: new Date(),
|
||||||
feature: {
|
feature: {
|
||||||
type: "Polygon",
|
type: "Feature",
|
||||||
properties:{
|
properties:{
|
||||||
id:"current_view"
|
id:"current_view-"+i,
|
||||||
|
"current_view":"yes"
|
||||||
},
|
},
|
||||||
geometry:{
|
geometry:{
|
||||||
type:"Polygon",
|
type:"Polygon",
|
||||||
coordinates:[
|
coordinates:[[
|
||||||
[bounds.maxLon, bounds.maxLat],
|
[bounds.maxLon, bounds.maxLat],
|
||||||
[bounds.minLon, bounds.maxLat],
|
[bounds.minLon, bounds.maxLat],
|
||||||
[bounds.minLon, bounds.minLat],
|
[bounds.minLon, bounds.minLat],
|
||||||
[bounds.maxLon, bounds.minLat],
|
[bounds.maxLon, bounds.minLat],
|
||||||
[bounds.maxLon, bounds.maxLat],
|
[bounds.maxLon, bounds.maxLat],
|
||||||
]
|
]]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return [feature]
|
return [feature]
|
||||||
})
|
})
|
||||||
let currentViewLayer: FilteredLayer = this.filteredLayers.data.filter(l => l.layerDef.id === "current_view")[0]
|
|
||||||
|
|
||||||
this.currentView = new SimpleFeatureSource(currentViewLayer,0,features)
|
this.currentView = new SimpleFeatureSource(currentViewLayer,0,features)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2,7 +2,7 @@ import {Utils} from "../Utils";
|
||||||
|
|
||||||
export default class Constants {
|
export default class Constants {
|
||||||
|
|
||||||
public static vNumber = "0.13.0-alpha-5";
|
public static vNumber = "0.13.0-alpha-6";
|
||||||
public static ImgurApiKey = '7070e7167f0a25a'
|
public static ImgurApiKey = '7070e7167f0a25a'
|
||||||
public static readonly mapillary_client_token_v4 = "MLY|4441509239301885|b40ad2d3ea105435bd40c7e76993ae85"
|
public static readonly mapillary_client_token_v4 = "MLY|4441509239301885|b40ad2d3ea105435bd40c7e76993ae85"
|
||||||
|
|
||||||
|
|
|
@ -15,10 +15,17 @@ import FilteredLayer from "../../Models/FilteredLayer";
|
||||||
import BaseLayer from "../../Models/BaseLayer";
|
import BaseLayer from "../../Models/BaseLayer";
|
||||||
import {OsmConnection} from "../../Logic/Osm/OsmConnection";
|
import {OsmConnection} from "../../Logic/Osm/OsmConnection";
|
||||||
import BackgroundMapSwitch from "./BackgroundMapSwitch";
|
import BackgroundMapSwitch from "./BackgroundMapSwitch";
|
||||||
|
import {FeatureSourceForLayer} from "../../Logic/FeatureSource/FeatureSource";
|
||||||
|
import Lazy from "../Base/Lazy";
|
||||||
|
import {VariableUiElement} from "../Base/VariableUIElement";
|
||||||
|
import FeatureInfoBox from "../Popup/FeatureInfoBox";
|
||||||
|
import {ElementStorage} from "../../Logic/ElementStorage";
|
||||||
|
|
||||||
export default class LeftControls extends Combine {
|
export default class LeftControls extends Combine {
|
||||||
|
|
||||||
constructor(state: {
|
constructor(state: {
|
||||||
|
allElements: ElementStorage;
|
||||||
|
currentView: FeatureSourceForLayer;
|
||||||
featureSwitchBackgroundSelection: UIEventSource<boolean>;
|
featureSwitchBackgroundSelection: UIEventSource<boolean>;
|
||||||
layoutToUse: LayoutConfig,
|
layoutToUse: LayoutConfig,
|
||||||
featurePipeline: FeaturePipeline,
|
featurePipeline: FeaturePipeline,
|
||||||
|
@ -33,12 +40,56 @@ export default class LeftControls extends Combine {
|
||||||
osmConnection: OsmConnection
|
osmConnection: OsmConnection
|
||||||
},
|
},
|
||||||
guiState: {
|
guiState: {
|
||||||
|
currentViewControlIsOpened: UIEventSource<boolean>;
|
||||||
downloadControlIsOpened: UIEventSource<boolean>,
|
downloadControlIsOpened: UIEventSource<boolean>,
|
||||||
filterViewIsOpened: UIEventSource<boolean>,
|
filterViewIsOpened: UIEventSource<boolean>,
|
||||||
copyrightViewIsOpened: UIEventSource<boolean>
|
copyrightViewIsOpened: UIEventSource<boolean>
|
||||||
}) {
|
}) {
|
||||||
|
|
||||||
|
|
||||||
|
const currentViewFL = state.currentView?.layer
|
||||||
|
const currentViewAction = new Toggle(
|
||||||
|
new Lazy(() => {
|
||||||
|
const feature : UIEventSource<any> = state.currentView.features.map(ffs => ffs[0]?.feature)
|
||||||
|
const icon = new VariableUiElement(feature.map(feature => {
|
||||||
|
const defaultIcon = Svg.checkbox_empty_svg()
|
||||||
|
if (feature === undefined) {
|
||||||
|
return defaultIcon;
|
||||||
|
}
|
||||||
|
const tags = {...feature.properties, button: "yes"}
|
||||||
|
const elem = currentViewFL.layerDef.mapRendering[0]?.GenerateLeafletStyle(tags, false, {
|
||||||
|
noSize: true
|
||||||
|
})?.html
|
||||||
|
if(elem === undefined){
|
||||||
|
return defaultIcon
|
||||||
|
}
|
||||||
|
return elem
|
||||||
|
}))
|
||||||
|
|
||||||
|
const featureBox = new VariableUiElement(feature.map(feature => {
|
||||||
|
if(feature === undefined){return undefined}
|
||||||
|
return new Lazy(() => {
|
||||||
|
const tagsSource= state.allElements.getEventSourceById(feature.properties.id)
|
||||||
|
return new FeatureInfoBox(tagsSource, currentViewFL.layerDef, "currentview", guiState.currentViewControlIsOpened)
|
||||||
|
})
|
||||||
|
}))
|
||||||
|
|
||||||
|
|
||||||
|
return new Toggle(
|
||||||
|
featureBox,
|
||||||
|
new MapControlButton(icon),
|
||||||
|
guiState.currentViewControlIsOpened
|
||||||
|
)
|
||||||
|
|
||||||
|
}).SetClass("inline-block w-full").onClick(() => {
|
||||||
|
guiState.currentViewControlIsOpened.setData(true)
|
||||||
|
}),
|
||||||
|
|
||||||
|
|
||||||
|
undefined,
|
||||||
|
new UIEventSource<boolean>(currentViewFL !== undefined && currentViewFL?.layerDef?.tagRenderings !== null)
|
||||||
|
)
|
||||||
|
|
||||||
const toggledDownload = new Toggle(
|
const toggledDownload = new Toggle(
|
||||||
new AllDownloads(
|
new AllDownloads(
|
||||||
guiState.downloadControlIsOpened
|
guiState.downloadControlIsOpened
|
||||||
|
@ -75,16 +126,18 @@ export default class LeftControls extends Combine {
|
||||||
undefined,
|
undefined,
|
||||||
state.featureSwitchFilter
|
state.featureSwitchFilter
|
||||||
);
|
);
|
||||||
|
|
||||||
const mapSwitch = new Toggle(
|
const mapSwitch = new Toggle(
|
||||||
new BackgroundMapSwitch(state, state.backgroundLayer),
|
new BackgroundMapSwitch(state, state.backgroundLayer),
|
||||||
undefined,
|
undefined,
|
||||||
state.featureSwitchBackgroundSelection
|
state.featureSwitchBackgroundSelection
|
||||||
)
|
)
|
||||||
|
|
||||||
super([filterButton,
|
super([
|
||||||
|
currentViewAction,
|
||||||
|
filterButton,
|
||||||
downloadButtonn,
|
downloadButtonn,
|
||||||
mapSwitch
|
mapSwitch
|
||||||
])
|
])
|
||||||
|
|
||||||
this.SetClass("flex flex-col")
|
this.SetClass("flex flex-col")
|
||||||
|
|
|
@ -9,6 +9,7 @@ export class DefaultGuiState {
|
||||||
public readonly downloadControlIsOpened: UIEventSource<boolean>;
|
public readonly downloadControlIsOpened: UIEventSource<boolean>;
|
||||||
public readonly filterViewIsOpened: UIEventSource<boolean>;
|
public readonly filterViewIsOpened: UIEventSource<boolean>;
|
||||||
public readonly copyrightViewIsOpened: UIEventSource<boolean>;
|
public readonly copyrightViewIsOpened: UIEventSource<boolean>;
|
||||||
|
public readonly currentViewControlIsOpened: UIEventSource<boolean>;
|
||||||
public readonly welcomeMessageOpenedTab: UIEventSource<number>
|
public readonly welcomeMessageOpenedTab: UIEventSource<number>
|
||||||
public readonly allFullScreenStates: UIEventSource<boolean>[] = []
|
public readonly allFullScreenStates: UIEventSource<boolean>[] = []
|
||||||
|
|
||||||
|
@ -40,6 +41,11 @@ export class DefaultGuiState {
|
||||||
"false",
|
"false",
|
||||||
"Whether or not the copyright view is shown"
|
"Whether or not the copyright view is shown"
|
||||||
)
|
)
|
||||||
|
this.currentViewControlIsOpened = QueryParameters.GetBooleanQueryParameter(
|
||||||
|
"currentview-toggle",
|
||||||
|
"false",
|
||||||
|
"Whether or not the current view box is shown"
|
||||||
|
)
|
||||||
if (Hash.hash.data === "download") {
|
if (Hash.hash.data === "download") {
|
||||||
this.downloadControlIsOpened.setData(true)
|
this.downloadControlIsOpened.setData(true)
|
||||||
}
|
}
|
||||||
|
@ -48,12 +54,14 @@ export class DefaultGuiState {
|
||||||
}
|
}
|
||||||
if (Hash.hash.data === "copyright") {
|
if (Hash.hash.data === "copyright") {
|
||||||
this.copyrightViewIsOpened.setData(true)
|
this.copyrightViewIsOpened.setData(true)
|
||||||
|
}if (Hash.hash.data === "currentview") {
|
||||||
|
this.currentViewControlIsOpened.setData(true)
|
||||||
}
|
}
|
||||||
if (Hash.hash.data === "" || Hash.hash.data === undefined || Hash.hash.data === "welcome") {
|
if (Hash.hash.data === "" || Hash.hash.data === undefined || Hash.hash.data === "welcome") {
|
||||||
this.welcomeMessageIsOpened.setData(true)
|
this.welcomeMessageIsOpened.setData(true)
|
||||||
}
|
}
|
||||||
|
|
||||||
this.allFullScreenStates.push(this.downloadControlIsOpened, this.filterViewIsOpened, this.copyrightViewIsOpened, this.welcomeMessageIsOpened)
|
this.allFullScreenStates.push(this.downloadControlIsOpened, this.filterViewIsOpened, this.copyrightViewIsOpened, this.welcomeMessageIsOpened, this.currentViewControlIsOpened)
|
||||||
|
|
||||||
for (let i = 0; i < this.allFullScreenStates.length; i++) {
|
for (let i = 0; i < this.allFullScreenStates.length; i++) {
|
||||||
const fullScreenState = this.allFullScreenStates[i];
|
const fullScreenState = this.allFullScreenStates[i];
|
||||||
|
|
|
@ -25,10 +25,13 @@ export default class FeatureInfoBox extends ScrollableFullScreen {
|
||||||
public constructor(
|
public constructor(
|
||||||
tags: UIEventSource<any>,
|
tags: UIEventSource<any>,
|
||||||
layerConfig: LayerConfig,
|
layerConfig: LayerConfig,
|
||||||
|
hashToShow?: string,
|
||||||
|
isShown?: UIEventSource<boolean>
|
||||||
) {
|
) {
|
||||||
super(() => FeatureInfoBox.GenerateTitleBar(tags, layerConfig),
|
super(() => FeatureInfoBox.GenerateTitleBar(tags, layerConfig),
|
||||||
() => FeatureInfoBox.GenerateContent(tags, layerConfig),
|
() => FeatureInfoBox.GenerateContent(tags, layerConfig),
|
||||||
tags.data.id);
|
hashToShow ?? tags.data.id,
|
||||||
|
isShown);
|
||||||
|
|
||||||
if (layerConfig === undefined) {
|
if (layerConfig === undefined) {
|
||||||
throw "Undefined layerconfig";
|
throw "Undefined layerconfig";
|
||||||
|
|
|
@ -180,8 +180,7 @@
|
||||||
"if": {
|
"if": {
|
||||||
"and": [
|
"and": [
|
||||||
"socket:schuko~*",
|
"socket:schuko~*",
|
||||||
"socket:schuko!=1",
|
"socket:schuko!=1"
|
||||||
""
|
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"then": {
|
"then": {
|
||||||
|
@ -202,8 +201,7 @@
|
||||||
"if": {
|
"if": {
|
||||||
"and": [
|
"and": [
|
||||||
"socket:typee~*",
|
"socket:typee~*",
|
||||||
"socket:typee!=1",
|
"socket:typee!=1"
|
||||||
""
|
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"then": {
|
"then": {
|
||||||
|
@ -250,8 +248,7 @@
|
||||||
"if": {
|
"if": {
|
||||||
"and": [
|
"and": [
|
||||||
"socket:chademo~*",
|
"socket:chademo~*",
|
||||||
"socket:chademo!=1",
|
"socket:chademo!=1"
|
||||||
""
|
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"then": {
|
"then": {
|
||||||
|
@ -298,8 +295,7 @@
|
||||||
"if": {
|
"if": {
|
||||||
"and": [
|
"and": [
|
||||||
"socket:type1_cable~*",
|
"socket:type1_cable~*",
|
||||||
"socket:type1_cable!=1",
|
"socket:type1_cable!=1"
|
||||||
""
|
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"then": {
|
"then": {
|
||||||
|
@ -346,8 +342,7 @@
|
||||||
"if": {
|
"if": {
|
||||||
"and": [
|
"and": [
|
||||||
"socket:type1~*",
|
"socket:type1~*",
|
||||||
"socket:type1!=1",
|
"socket:type1!=1"
|
||||||
""
|
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"then": {
|
"then": {
|
||||||
|
@ -394,8 +389,7 @@
|
||||||
"if": {
|
"if": {
|
||||||
"and": [
|
"and": [
|
||||||
"socket:type1_combo~*",
|
"socket:type1_combo~*",
|
||||||
"socket:type1_combo!=1",
|
"socket:type1_combo!=1"
|
||||||
""
|
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"then": {
|
"then": {
|
||||||
|
@ -442,8 +436,7 @@
|
||||||
"if": {
|
"if": {
|
||||||
"and": [
|
"and": [
|
||||||
"socket:tesla_supercharger~*",
|
"socket:tesla_supercharger~*",
|
||||||
"socket:tesla_supercharger!=1",
|
"socket:tesla_supercharger!=1"
|
||||||
""
|
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"then": {
|
"then": {
|
||||||
|
@ -490,8 +483,7 @@
|
||||||
"if": {
|
"if": {
|
||||||
"and": [
|
"and": [
|
||||||
"socket:type2~*",
|
"socket:type2~*",
|
||||||
"socket:type2!=1",
|
"socket:type2!=1"
|
||||||
""
|
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"then": {
|
"then": {
|
||||||
|
@ -538,8 +530,7 @@
|
||||||
"if": {
|
"if": {
|
||||||
"and": [
|
"and": [
|
||||||
"socket:type2_combo~*",
|
"socket:type2_combo~*",
|
||||||
"socket:type2_combo!=1",
|
"socket:type2_combo!=1"
|
||||||
""
|
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"then": {
|
"then": {
|
||||||
|
@ -586,8 +577,7 @@
|
||||||
"if": {
|
"if": {
|
||||||
"and": [
|
"and": [
|
||||||
"socket:type2_cable~*",
|
"socket:type2_cable~*",
|
||||||
"socket:type2_cable!=1",
|
"socket:type2_cable!=1"
|
||||||
""
|
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"then": {
|
"then": {
|
||||||
|
@ -634,8 +624,7 @@
|
||||||
"if": {
|
"if": {
|
||||||
"and": [
|
"and": [
|
||||||
"socket:tesla_supercharger_ccs~*",
|
"socket:tesla_supercharger_ccs~*",
|
||||||
"socket:tesla_supercharger_ccs!=1",
|
"socket:tesla_supercharger_ccs!=1"
|
||||||
""
|
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"then": {
|
"then": {
|
||||||
|
@ -762,8 +751,7 @@
|
||||||
"if": {
|
"if": {
|
||||||
"and": [
|
"and": [
|
||||||
"socket:USB-A~*",
|
"socket:USB-A~*",
|
||||||
"socket:USB-A!=1",
|
"socket:USB-A!=1"
|
||||||
""
|
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"then": {
|
"then": {
|
||||||
|
@ -806,8 +794,7 @@
|
||||||
"if": {
|
"if": {
|
||||||
"and": [
|
"and": [
|
||||||
"socket:bosch_3pin~*",
|
"socket:bosch_3pin~*",
|
||||||
"socket:bosch_3pin!=1",
|
"socket:bosch_3pin!=1"
|
||||||
""
|
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"then": {
|
"then": {
|
||||||
|
@ -850,8 +837,7 @@
|
||||||
"if": {
|
"if": {
|
||||||
"and": [
|
"and": [
|
||||||
"socket:bosch_5pin~*",
|
"socket:bosch_5pin~*",
|
||||||
"socket:bosch_5pin!=1",
|
"socket:bosch_5pin!=1"
|
||||||
""
|
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"then": {
|
"then": {
|
||||||
|
|
|
@ -3,7 +3,6 @@ import {Utils} from "../../../Utils";
|
||||||
import {TagRenderingConfigJson} from "../../../Models/ThemeConfig/Json/TagRenderingConfigJson";
|
import {TagRenderingConfigJson} from "../../../Models/ThemeConfig/Json/TagRenderingConfigJson";
|
||||||
import ScriptUtils from "../../../scripts/ScriptUtils";
|
import ScriptUtils from "../../../scripts/ScriptUtils";
|
||||||
import {LayerConfigJson} from "../../../Models/ThemeConfig/Json/LayerConfigJson";
|
import {LayerConfigJson} from "../../../Models/ThemeConfig/Json/LayerConfigJson";
|
||||||
import {TagsFilter} from "../../../Logic/Tags/TagsFilter";
|
|
||||||
|
|
||||||
|
|
||||||
function colonSplit(value: string): string[] {
|
function colonSplit(value: string): string[] {
|
||||||
|
@ -122,7 +121,7 @@ function run(file, protojson) {
|
||||||
// We add a second time for any amount to trigger a visualisation; but this is not an answer option
|
// We add a second time for any amount to trigger a visualisation; but this is not an answer option
|
||||||
const no_ask_json = {
|
const no_ask_json = {
|
||||||
if: {
|
if: {
|
||||||
and:Utils.NoNull( [`${e.key}~*`, `${e.key}!=1`, ...e.extraVisualisationCondition.split(";")])
|
and:Utils.NoEmpty( [`${e.key}~*`, `${e.key}!=1`, ...e.extraVisualisationCondition.split(";")])
|
||||||
},
|
},
|
||||||
then: txt,
|
then: txt,
|
||||||
hideInAnswer: true
|
hideInAnswer: true
|
||||||
|
|
|
@ -1,9 +1,10 @@
|
||||||
{
|
{
|
||||||
"id": "current_view",
|
"id": "current_view",
|
||||||
"description": "A meta-layer which contains one single feature, namely the BBOX of the current map view. This can be used to trigger special actions. If a popup is defined for this layer, this popup will be accessible via an extra button on screen",
|
"description": "A meta-layer which contains one single feature, namely the BBOX of the current map view. This can be used to trigger special actions. If a popup is defined for this layer, this popup will be accessible via an extra button on screen.\n\nThe icon on the button is the default icon of the layer, but can be customized by detecting 'button=yes'.",
|
||||||
"source": {
|
"source": {
|
||||||
"osmTags": "id=currentView"
|
"osmTags": "current_view=yes"
|
||||||
},
|
},
|
||||||
|
"shownByDefault": false,
|
||||||
"title": "Current View",
|
"title": "Current View",
|
||||||
"tagRenderings": [],
|
"tagRenderings": [],
|
||||||
"mapRendering": [
|
"mapRendering": [
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue