forked from MapComplete/MapComplete
More refactoring, stabilizing rotation and direction_gradient
This commit is contained in:
parent
5fec108ba2
commit
778044d0fb
45 changed files with 656 additions and 640 deletions
|
@ -1,53 +1,45 @@
|
|||
import Translations from "./UI/i18n/Translations";
|
||||
import {TabbedComponent} from "./UI/Base/TabbedComponent";
|
||||
import {ShareScreen} from "./UI/ShareScreen";
|
||||
import {FixedUiElement} from "./UI/Base/FixedUiElement";
|
||||
import CheckBox from "./UI/Input/CheckBox";
|
||||
import Combine from "./UI/Base/Combine";
|
||||
import {UIElement} from "./UI/UIElement";
|
||||
import {MoreScreen} from "./UI/MoreScreen";
|
||||
import {FilteredLayer} from "./Logic/FilteredLayer";
|
||||
import {Basemap} from "./UI/Basemap";
|
||||
import {Basemap} from "./UI/BigComponents/Basemap";
|
||||
import State from "./State";
|
||||
import {WelcomeMessage} from "./UI/WelcomeMessage";
|
||||
import {LayerSelection} from "./UI/LayerSelection";
|
||||
import {VariableUiElement} from "./UI/Base/VariableUIElement";
|
||||
import LoadFromOverpass from "./Logic/Actors/UpdateFromOverpass";
|
||||
import {UIEventSource} from "./Logic/UIEventSource";
|
||||
import {QueryParameters} from "./Logic/Web/QueryParameters";
|
||||
import {PersonalLayersPanel} from "./UI/PersonalLayersPanel";
|
||||
import Locale from "./UI/i18n/Locale";
|
||||
import {StrayClickHandler} from "./Logic/Actors/StrayClickHandler";
|
||||
import {SimpleAddUI} from "./UI/SimpleAddUI";
|
||||
import {CenterMessageBox} from "./UI/CenterMessageBox";
|
||||
import StrayClickHandler from "./Logic/Actors/StrayClickHandler";
|
||||
import SimpleAddUI from "./UI/BigComponents/SimpleAddUI";
|
||||
import CenterMessageBox from "./UI/CenterMessageBox";
|
||||
import {AllKnownLayouts} from "./Customizations/AllKnownLayouts";
|
||||
import {TagUtils} from "./Logic/Tags";
|
||||
import {UserBadge} from "./UI/UserBadge";
|
||||
import {SearchAndGo} from "./UI/SearchAndGo";
|
||||
import {FullScreenMessageBox} from "./UI/FullScreenMessageBoxHandler";
|
||||
import {GeoLocationHandler} from "./Logic/Actors/GeoLocationHandler";
|
||||
import UserBadge from "./UI/BigComponents/UserBadge";
|
||||
import SearchAndGo from "./UI/BigComponents/SearchAndGo";
|
||||
import FullScreenMessageBox from "./UI/FullScreenMessageBoxHandler";
|
||||
import GeoLocationHandler from "./Logic/Actors/GeoLocationHandler";
|
||||
import {LocalStorageSource} from "./Logic/Web/LocalStorageSource";
|
||||
import {Utils} from "./Utils";
|
||||
import BackgroundSelector from "./UI/BackgroundSelector";
|
||||
import {FeatureInfoBox} from "./UI/Popup/FeatureInfoBox";
|
||||
import FeatureInfoBox from "./UI/Popup/FeatureInfoBox";
|
||||
import Svg from "./Svg";
|
||||
import Link from "./UI/Base/Link";
|
||||
import * as personal from "./assets/themes/personalLayout/personalLayout.json"
|
||||
import LayoutConfig from "./Customizations/JSON/LayoutConfig";
|
||||
import * as L from "leaflet";
|
||||
import Img from "./UI/Base/Img";
|
||||
import {UserDetails} from "./Logic/Osm/OsmConnection";
|
||||
import Attribution from "./UI/Misc/Attribution";
|
||||
import Constants from "./Models/Constants";
|
||||
import UserDetails from "./Logic/Osm/OsmConnection";
|
||||
import Attribution from "./UI/BigComponents/Attribution";
|
||||
import MetaTagging from "./Logic/MetaTagging";
|
||||
import FeatureSourceMerger from "./Logic/FeatureSource/FeatureSourceMerger";
|
||||
import RememberingSource from "./Logic/FeatureSource/RememberingSource";
|
||||
import FilteringFeatureSource from "./Logic/FeatureSource/FilteringFeatureSource";
|
||||
import WayHandlingApplyingFeatureSource from "./Logic/FeatureSource/WayHandlingApplyingFeatureSource";
|
||||
import FeatureSource from "./Logic/FeatureSource/FeatureSource";
|
||||
import NoOverlapSource from "./Logic/FeatureSource/NoOverlapSource";
|
||||
import AvailableBaseLayers from "./Logic/Actors/AvailableBaseLayers";
|
||||
import LayerResetter from "./Logic/Actors/LayerResetter";
|
||||
import FullWelcomePaneWithTabs from "./UI/BigComponents/FullWelcomePaneWithTabs";
|
||||
import LayerControlPanel from "./UI/BigComponents/LayerControlPanel";
|
||||
import FeatureSwitched from "./UI/Base/FeatureSwitched";
|
||||
import FeatureDuplicatorPerLayer from "./Logic/FeatureSource/FeatureDuplicatorPerLayer";
|
||||
import LayerConfig from "./Customizations/JSON/LayerConfig";
|
||||
import ShowDataLayer from "./UI/ShowDataLayer";
|
||||
|
||||
export class InitUiElements {
|
||||
|
||||
|
@ -87,10 +79,6 @@ export class InitUiElements {
|
|||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
InitUiElements.InitBaseMap();
|
||||
|
||||
new FixedUiElement("").AttachTo("decoration-desktop"); // Remove the decoration
|
||||
|
@ -216,13 +204,15 @@ export class InitUiElements {
|
|||
marker.addTo(State.state.leafletMap.data)
|
||||
});
|
||||
|
||||
new GeoLocationHandler(
|
||||
State.state.currentGPSLocation,
|
||||
State.state.leafletMap,
|
||||
State.state.featureSwitchGeolocation
|
||||
)
|
||||
.SetStyle(`position:relative;display:block;border: solid 2px #0005;cursor: pointer; z-index: 999; /*Just below leaflets zoom*/background-color: white;border-radius: 5px;width: 43px;height: 43px;`)
|
||||
new FeatureSwitched(
|
||||
new GeoLocationHandler(
|
||||
State.state.currentGPSLocation,
|
||||
State.state.leafletMap
|
||||
)
|
||||
.SetStyle(`position:relative;display:block;border: solid 2px #0005;cursor: pointer; z-index: 999; /*Just below leaflets zoom*/background-color: white;border-radius: 5px;width: 43px;height: 43px;`)
|
||||
, State.state.featureSwitchGeolocation)
|
||||
.AttachTo("geolocate-button");
|
||||
|
||||
State.state.locationControl.ping();
|
||||
}
|
||||
|
||||
|
@ -254,23 +244,18 @@ export class InitUiElements {
|
|||
}
|
||||
}
|
||||
|
||||
static OnlyIf(featureSwitch: UIEventSource<boolean>, callback: () => void) {
|
||||
featureSwitch.addCallback(() => {
|
||||
private static OnlyIf(featureSwitch: UIEventSource<boolean>, callback: () => void) {
|
||||
featureSwitch.addCallbackAndRun(() => {
|
||||
|
||||
if (featureSwitch.data) {
|
||||
callback();
|
||||
}
|
||||
});
|
||||
|
||||
if (featureSwitch.data) {
|
||||
callback();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static InitWelcomeMessage() {
|
||||
private static InitWelcomeMessage() {
|
||||
|
||||
const fullOptions = this.CreateWelcomePane();
|
||||
const fullOptions = new FullWelcomePaneWithTabs();
|
||||
|
||||
const help = Svg.help_svg().SetClass("open-welcome-button");
|
||||
const close = Svg.close_svg().SetClass("close-welcome-button");
|
||||
|
@ -298,7 +283,7 @@ export class InitUiElements {
|
|||
})
|
||||
|
||||
|
||||
const fullOptions2 = this.CreateWelcomePane();
|
||||
const fullOptions2 = new FullWelcomePaneWithTabs();
|
||||
State.state.fullScreenMessage.setData(fullOptions2)
|
||||
|
||||
Svg.help_svg()
|
||||
|
@ -311,15 +296,11 @@ export class InitUiElements {
|
|||
|
||||
}
|
||||
|
||||
static InitLayerSelection() {
|
||||
private static InitLayerSelection() {
|
||||
InitUiElements.OnlyIf(State.state.featureSwitchLayers, () => {
|
||||
|
||||
const layerControlPanel = this.GenerateLayerControlPanel();
|
||||
if (layerControlPanel === undefined) {
|
||||
return;
|
||||
}
|
||||
|
||||
layerControlPanel.SetStyle("display:block;padding:0.75em;border-radius:1em;");
|
||||
const layerControlPanel = new LayerControlPanel()
|
||||
.SetStyle("display:block;padding:0.75em;border-radius:1em;");
|
||||
const closeButton = Svg.close_svg().SetClass("layer-selection-toggle").SetStyle(" background: var(--subtle-detail-color);")
|
||||
const checkbox = new CheckBox(
|
||||
new Combine([
|
||||
|
@ -334,18 +315,19 @@ export class InitUiElements {
|
|||
checkbox.AttachTo("layer-selection");
|
||||
|
||||
|
||||
State.state.locationControl.addCallback(() => {
|
||||
State.state.locationControl
|
||||
.addCallback(() => {
|
||||
// Close the layer selection when the map is moved
|
||||
checkbox.isEnabled.setData(false);
|
||||
// checkbox.isEnabled.setData(false);
|
||||
});
|
||||
|
||||
const fullScreen = this.GenerateLayerControlPanel();
|
||||
const fullScreen = new LayerControlPanel();
|
||||
checkbox.isEnabled.addCallback(isEnabled => {
|
||||
if (isEnabled) {
|
||||
State.state.fullScreenMessage.setData(fullScreen);
|
||||
}
|
||||
})
|
||||
State.state.fullScreenMessage.addCallbackAndRun(latest => {
|
||||
State.state.fullScreenMessage.addCallback(latest => {
|
||||
if (latest === undefined) {
|
||||
checkbox.isEnabled.setData(false);
|
||||
}
|
||||
|
@ -354,7 +336,7 @@ export class InitUiElements {
|
|||
});
|
||||
}
|
||||
|
||||
static InitBaseMap() {
|
||||
private static InitBaseMap() {
|
||||
|
||||
State.state.availableBackgroundLayers = new AvailableBaseLayers(State.state.locationControl).availableEditorLayers;
|
||||
State.state.backgroundLayer = QueryParameters.GetQueryParameter("background",
|
||||
|
@ -371,8 +353,6 @@ export class InitUiElements {
|
|||
}, [], layer => layer.id);
|
||||
|
||||
|
||||
|
||||
|
||||
new LayerResetter(
|
||||
State.state.backgroundLayer, State.state.locationControl,
|
||||
State.state.availableBackgroundLayers, State.state.layoutToUse.map((layout: LayoutConfig) => layout.defaultBackgroundId));
|
||||
|
@ -393,61 +373,33 @@ export class InitUiElements {
|
|||
|
||||
}
|
||||
|
||||
static InitLayers() {
|
||||
|
||||
|
||||
private static InitLayers() {
|
||||
|
||||
|
||||
const state = State.state;
|
||||
const flayers: FilteredLayer[] = []
|
||||
const flayers: { layerDef: LayerConfig, isDisplayed: UIEventSource<boolean> }[] = []
|
||||
for (const layer of state.layoutToUse.data.layers) {
|
||||
|
||||
if (typeof (layer) === "string") {
|
||||
throw "Layer " + layer + " was not substituted";
|
||||
}
|
||||
|
||||
let generateContents = (tags: UIEventSource<any>) => new FeatureInfoBox(tags, layer);
|
||||
if (layer.title === undefined && (layer.tagRenderings ?? []).length === 0) {
|
||||
generateContents = undefined;
|
||||
const isDisplayed = QueryParameters.GetQueryParameter("layer-" + layer.id, "true", "Wether or not layer " + layer.id + " is shown")
|
||||
.map<boolean>((str) => str !== "false", [], (b) => b.toString());
|
||||
const flayer = {
|
||||
isDisplayed: isDisplayed,
|
||||
layerDef: layer
|
||||
}
|
||||
|
||||
const flayer: FilteredLayer = new FilteredLayer(layer, generateContents);
|
||||
flayers.push(flayer);
|
||||
|
||||
QueryParameters.GetQueryParameter("layer-" + layer.id, "true", "Wether or not layer " + layer.id + " is shown")
|
||||
.map<boolean>((str) => str !== "false", [], (b) => b.toString())
|
||||
.syncWith(
|
||||
flayer.isDisplayed
|
||||
)
|
||||
}
|
||||
|
||||
State.state.filteredLayers.setData(flayers);
|
||||
|
||||
function addMatchingIds(src: FeatureSource) {
|
||||
|
||||
src.features.addCallback(features => {
|
||||
features.forEach(f => {
|
||||
const properties = f.feature.properties;
|
||||
if (properties._matching_layer_id) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (const flayer of flayers) {
|
||||
if (flayer.layerDef.overpassTags.matchesProperties(properties)) {
|
||||
properties._matching_layer_id = flayer.layerDef.id;
|
||||
break;
|
||||
}
|
||||
}
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
const updater = new LoadFromOverpass(state.locationControl, state.layoutToUse, state.leafletMap);
|
||||
State.state.layerUpdater = updater;
|
||||
|
||||
addMatchingIds(updater);
|
||||
addMatchingIds(State.state.changes);
|
||||
|
||||
|
||||
|
||||
const source =
|
||||
new FilteringFeatureSource(
|
||||
|
@ -455,9 +407,9 @@ export class InitUiElements {
|
|||
State.state.locationControl,
|
||||
new FeatureSourceMerger([
|
||||
new RememberingSource(new WayHandlingApplyingFeatureSource(flayers,
|
||||
new NoOverlapSource(flayers, updater)
|
||||
new NoOverlapSource(flayers, new FeatureDuplicatorPerLayer(flayers, updater))
|
||||
)),
|
||||
State.state.changes]));
|
||||
new FeatureDuplicatorPerLayer(flayers, State.state.changes)]));
|
||||
|
||||
|
||||
source.features.addCallback((featuresFreshness: { feature: any, freshness: Date }[]) => {
|
||||
|
@ -466,25 +418,9 @@ export class InitUiElements {
|
|||
State.state.allElements.addElement(feature);
|
||||
})
|
||||
MetaTagging.addMetatags(features);
|
||||
|
||||
function renderLayers(layers) {
|
||||
|
||||
|
||||
if (layers.length === 0) {
|
||||
if (features.length > 0) {
|
||||
console.warn("Got some leftovers: ", features.join("; "))
|
||||
}
|
||||
return;
|
||||
}
|
||||
const layer = layers[0];
|
||||
const rest = layers.slice(1, layers.length);
|
||||
features = layer.SetApplicableData(features);
|
||||
renderLayers(rest);
|
||||
}
|
||||
|
||||
renderLayers(flayers);
|
||||
|
||||
})
|
||||
|
||||
new ShowDataLayer(source.features, State.state.leafletMap, flayers);
|
||||
|
||||
|
||||
}
|
||||
|
@ -528,72 +464,4 @@ export class InitUiElements {
|
|||
new CenterMessageBox().AttachTo("centermessage");
|
||||
|
||||
}
|
||||
|
||||
private static CreateWelcomePane() {
|
||||
|
||||
const layoutToUse = State.state.layoutToUse.data;
|
||||
let welcome: UIElement = new WelcomeMessage();
|
||||
if (layoutToUse.id === personal.id) {
|
||||
welcome = new PersonalLayersPanel();
|
||||
}
|
||||
|
||||
const tabs = [
|
||||
{header: `<img src='${layoutToUse.icon}'>`, content: welcome},
|
||||
{
|
||||
header: Svg.osm_logo_img,
|
||||
content: Translations.t.general.openStreetMapIntro as UIElement
|
||||
},
|
||||
|
||||
]
|
||||
|
||||
if (State.state.featureSwitchShareScreen.data) {
|
||||
tabs.push({header: Svg.share_img, content: new ShareScreen()});
|
||||
}
|
||||
|
||||
if (State.state.featureSwitchMoreQuests.data) {
|
||||
|
||||
tabs.push({
|
||||
header: Svg.add_img,
|
||||
content: new MoreScreen()
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
tabs.push({
|
||||
header: Svg.help,
|
||||
content: new VariableUiElement(State.state.osmConnection.userDetails.map(userdetails => {
|
||||
if (userdetails.csCount < Constants.userJourney.mapCompleteHelpUnlock) {
|
||||
return ""
|
||||
}
|
||||
return new Combine([Translations.t.general.aboutMapcomplete, "<br/>Version " + Constants.vNumber]).Render();
|
||||
}, [Locale.language]))
|
||||
}
|
||||
);
|
||||
|
||||
|
||||
return new TabbedComponent(tabs, State.state.welcomeMessageOpenedTab)
|
||||
.ListenTo(State.state.osmConnection.userDetails);
|
||||
|
||||
}
|
||||
|
||||
private static GenerateLayerControlPanel() {
|
||||
|
||||
|
||||
let layerControlPanel: UIElement = undefined;
|
||||
if (State.state.layoutToUse.data.enableBackgroundLayerSelection) {
|
||||
layerControlPanel = new BackgroundSelector();
|
||||
layerControlPanel.SetStyle("margin:1em");
|
||||
layerControlPanel.onClick(() => {
|
||||
});
|
||||
}
|
||||
|
||||
if (State.state.filteredLayers.data.length > 1) {
|
||||
const layerSelection = new LayerSelection();
|
||||
layerSelection.onClick(() => {
|
||||
});
|
||||
layerControlPanel = new Combine([layerSelection, "<br/>", layerControlPanel]);
|
||||
}
|
||||
return layerControlPanel;
|
||||
}
|
||||
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue