Merge branch 'develop' of github.com:pietervdvn/MapComplete into develop
This commit is contained in:
commit
9623afeec9
46 changed files with 1300 additions and 1032 deletions
|
@ -23,11 +23,11 @@ export default class AvailableBaseLayers {
|
|||
private static implementation: AvailableBaseLayersObj
|
||||
|
||||
static AvailableLayersAt(location: UIEventSource<Loc>): UIEventSource<BaseLayer[]> {
|
||||
return AvailableBaseLayers.implementation.AvailableLayersAt(location);
|
||||
return AvailableBaseLayers.implementation?.AvailableLayersAt(location) ?? new UIEventSource<BaseLayer[]>([]);
|
||||
}
|
||||
|
||||
static SelectBestLayerAccordingTo(location: UIEventSource<Loc>, preferedCategory: UIEventSource<string | string[]>): UIEventSource<BaseLayer> {
|
||||
return AvailableBaseLayers.implementation.SelectBestLayerAccordingTo(location, preferedCategory);
|
||||
return AvailableBaseLayers.implementation?.SelectBestLayerAccordingTo(location, preferedCategory) ?? new UIEventSource<BaseLayer>(undefined);
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -2,6 +2,7 @@ import {UIEventSource} from "../UIEventSource";
|
|||
import BaseLayer from "../../Models/BaseLayer";
|
||||
import AvailableBaseLayers from "./AvailableBaseLayers";
|
||||
import Loc from "../../Models/Loc";
|
||||
import {Utils} from "../../Utils";
|
||||
|
||||
/**
|
||||
* Sets the current background layer to a layer that is actually available
|
||||
|
@ -12,6 +13,11 @@ export default class BackgroundLayerResetter {
|
|||
location: UIEventSource<Loc>,
|
||||
availableLayers: UIEventSource<BaseLayer[]>,
|
||||
defaultLayerId: string = undefined) {
|
||||
|
||||
if(Utils.runningFromConsole){
|
||||
return
|
||||
}
|
||||
|
||||
defaultLayerId = defaultLayerId ?? AvailableBaseLayers.osmCarto.id;
|
||||
|
||||
// Change the baselayer back to OSM if we go out of the current range of the layer
|
||||
|
|
|
@ -29,7 +29,7 @@ export default class OverpassFeatureSource implements FeatureSource {
|
|||
|
||||
|
||||
private readonly retries: UIEventSource<number> = new UIEventSource<number>(0);
|
||||
|
||||
|
||||
private readonly state: {
|
||||
readonly locationControl: UIEventSource<Loc>,
|
||||
readonly layoutToUse: LayoutConfig,
|
||||
|
@ -39,6 +39,7 @@ export default class OverpassFeatureSource implements FeatureSource {
|
|||
}
|
||||
private readonly _isActive: UIEventSource<boolean>;
|
||||
private readonly onBboxLoaded: (bbox: BBox, date: Date, layers: LayerConfig[], zoomlevel: number) => void;
|
||||
|
||||
constructor(
|
||||
state: {
|
||||
readonly locationControl: UIEventSource<Loc>,
|
||||
|
@ -90,7 +91,7 @@ export default class OverpassFeatureSource implements FeatureSource {
|
|||
}
|
||||
const self = this;
|
||||
this.updateAsync(paddedZoomLevel).then(bboxDate => {
|
||||
if(bboxDate === undefined || self.onBboxLoaded === undefined){
|
||||
if (bboxDate === undefined || self.onBboxLoaded === undefined) {
|
||||
return;
|
||||
}
|
||||
const [bbox, date, layers] = bboxDate
|
||||
|
@ -109,41 +110,43 @@ export default class OverpassFeatureSource implements FeatureSource {
|
|||
return undefined;
|
||||
}
|
||||
|
||||
const bounds = this.state.currentBounds.data?.pad(this.state.layoutToUse.widenFactor)?.expandToTileBounds(padToZoomLevel);
|
||||
|
||||
if (bounds === undefined) {
|
||||
return undefined;
|
||||
}
|
||||
const self = this;
|
||||
|
||||
|
||||
const layersToDownload = []
|
||||
for (const layer of this.state.layoutToUse.layers) {
|
||||
|
||||
if (typeof (layer) === "string") {
|
||||
throw "A layer was not expanded!"
|
||||
}
|
||||
if(this.state.locationControl.data.zoom < layer.minzoom){
|
||||
continue;
|
||||
}
|
||||
if (layer.doNotDownload) {
|
||||
continue;
|
||||
}
|
||||
if (layer.source.geojsonSource !== undefined) {
|
||||
// Not our responsibility to download this layer!
|
||||
continue;
|
||||
}
|
||||
layersToDownload.push(layer)
|
||||
}
|
||||
|
||||
let data: any = undefined
|
||||
let date: Date = undefined
|
||||
const overpassUrls = self.state.overpassUrl.data
|
||||
let lastUsed = 0;
|
||||
|
||||
|
||||
|
||||
const layersToDownload = []
|
||||
for (const layer of this.state.layoutToUse.layers) {
|
||||
|
||||
if (typeof (layer) === "string") {
|
||||
throw "A layer was not expanded!"
|
||||
}
|
||||
if (this.state.locationControl.data.zoom < layer.minzoom) {
|
||||
continue;
|
||||
}
|
||||
if (layer.doNotDownload) {
|
||||
continue;
|
||||
}
|
||||
if (layer.source.geojsonSource !== undefined) {
|
||||
// Not our responsibility to download this layer!
|
||||
continue;
|
||||
}
|
||||
layersToDownload.push(layer)
|
||||
}
|
||||
|
||||
const self = this;
|
||||
const overpassUrls = self.state.overpassUrl.data
|
||||
let bounds : BBox
|
||||
do {
|
||||
try {
|
||||
|
||||
|
||||
bounds = this.state.currentBounds.data?.pad(this.state.layoutToUse.widenFactor)?.expandToTileBounds(padToZoomLevel);
|
||||
|
||||
if (bounds === undefined) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
const overpass = this.GetFilter(overpassUrls[lastUsed], layersToDownload);
|
||||
|
||||
if (overpass === undefined) {
|
||||
|
@ -175,16 +178,21 @@ export default class OverpassFeatureSource implements FeatureSource {
|
|||
}
|
||||
}
|
||||
}
|
||||
} while (data === undefined);
|
||||
} while (data === undefined && this._isActive.data);
|
||||
|
||||
self.retries.setData(0);
|
||||
|
||||
try {
|
||||
if(data === undefined){
|
||||
return undefined
|
||||
}
|
||||
data.features.forEach(feature => SimpleMetaTagger.objectMetaInfo.applyMetaTagsOnFeature(feature, date, undefined));
|
||||
self.features.setData(data.features.map(f => ({feature: f, freshness: date})));
|
||||
return [bounds, date, layersToDownload];
|
||||
} catch (e) {
|
||||
console.error("Got the overpass response, but could not process it: ", e, e.stack)
|
||||
return undefined
|
||||
} finally {
|
||||
self.retries.setData(0);
|
||||
self.runningQuery.setData(false);
|
||||
}
|
||||
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
import {Changes} from "../Osm/Changes";
|
||||
import Constants from "../../Models/Constants";
|
||||
import {UIEventSource} from "../UIEventSource";
|
||||
import {Utils} from "../../Utils";
|
||||
|
||||
export default class PendingChangesUploader {
|
||||
|
||||
|
@ -30,6 +31,10 @@ export default class PendingChangesUploader {
|
|||
}
|
||||
});
|
||||
|
||||
if(Utils.runningFromConsole){
|
||||
return;
|
||||
}
|
||||
|
||||
document.addEventListener('mouseout', e => {
|
||||
// @ts-ignore
|
||||
if (!e.toElement && !e.relatedTarget) {
|
||||
|
|
|
@ -9,6 +9,13 @@ import {OsmConnection} from "../Osm/OsmConnection";
|
|||
|
||||
export default class SelectedElementTagsUpdater {
|
||||
|
||||
private static readonly metatags = new Set(["timestamp",
|
||||
"version",
|
||||
"changeset",
|
||||
"user",
|
||||
"uid",
|
||||
"id"] )
|
||||
|
||||
constructor(state: {
|
||||
selectedElement: UIEventSource<any>,
|
||||
allElements: ElementStorage,
|
||||
|
@ -18,15 +25,15 @@ export default class SelectedElementTagsUpdater {
|
|||
|
||||
|
||||
state.osmConnection.isLoggedIn.addCallbackAndRun(isLoggedIn => {
|
||||
if(isLoggedIn){
|
||||
if (isLoggedIn) {
|
||||
SelectedElementTagsUpdater.installCallback(state)
|
||||
return true;
|
||||
}
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
private static installCallback(state: {
|
||||
|
||||
public static installCallback(state: {
|
||||
selectedElement: UIEventSource<any>,
|
||||
allElements: ElementStorage,
|
||||
changes: Changes,
|
||||
|
@ -36,80 +43,99 @@ export default class SelectedElementTagsUpdater {
|
|||
|
||||
state.selectedElement.addCallbackAndRunD(s => {
|
||||
let id = s.properties?.id
|
||||
|
||||
|
||||
const backendUrl = state.osmConnection._oauth_config.url
|
||||
if(id.startsWith(backendUrl)){
|
||||
if (id.startsWith(backendUrl)) {
|
||||
id = id.substring(backendUrl.length)
|
||||
}
|
||||
|
||||
if(!(id.startsWith("way") || id.startsWith("node") || id.startsWith("relation"))){
|
||||
|
||||
if (!(id.startsWith("way") || id.startsWith("node") || id.startsWith("relation"))) {
|
||||
// This object is _not_ from OSM, so we skip it!
|
||||
return;
|
||||
}
|
||||
|
||||
if(id.indexOf("-") >= 0){
|
||||
|
||||
if (id.indexOf("-") >= 0) {
|
||||
// This is a new object
|
||||
return;
|
||||
}
|
||||
|
||||
OsmObject.DownloadPropertiesOf(id).then(tags => {
|
||||
SelectedElementTagsUpdater.applyUpdate(state, tags, id)
|
||||
}).catch(e => {
|
||||
console.error("Could not update tags of ", id, "due to", e)
|
||||
OsmObject.DownloadPropertiesOf(id).then(latestTags => {
|
||||
SelectedElementTagsUpdater.applyUpdate(state, latestTags, id)
|
||||
})
|
||||
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
private static applyUpdate(state: {
|
||||
selectedElement: UIEventSource<any>,
|
||||
allElements: ElementStorage,
|
||||
changes: Changes,
|
||||
osmConnection: OsmConnection
|
||||
}, latestTags: any, id: string
|
||||
public static applyUpdate(state: {
|
||||
selectedElement: UIEventSource<any>,
|
||||
allElements: ElementStorage,
|
||||
changes: Changes,
|
||||
osmConnection: OsmConnection
|
||||
}, latestTags: any, id: string
|
||||
) {
|
||||
const pendingChanges = state.changes.pendingChanges.data
|
||||
.filter(change => change.type +"/"+ change.id === id)
|
||||
.filter(change => change.tags !== undefined);
|
||||
|
||||
for (const pendingChange of pendingChanges) {
|
||||
const tagChanges = pendingChange.tags;
|
||||
for (const tagChange of tagChanges) {
|
||||
const key = tagChange.k
|
||||
const v = tagChange.v
|
||||
if (v === undefined || v === "") {
|
||||
delete latestTags[key]
|
||||
} else {
|
||||
latestTags[key] = v
|
||||
try {
|
||||
|
||||
const pendingChanges = state.changes.pendingChanges.data
|
||||
.filter(change => change.type + "/" + change.id === id)
|
||||
.filter(change => change.tags !== undefined);
|
||||
|
||||
for (const pendingChange of pendingChanges) {
|
||||
const tagChanges = pendingChange.tags;
|
||||
for (const tagChange of tagChanges) {
|
||||
const key = tagChange.k
|
||||
const v = tagChange.v
|
||||
if (v === undefined || v === "") {
|
||||
delete latestTags[key]
|
||||
} else {
|
||||
latestTags[key] = v
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// With the changes applied, we merge them onto the upstream object
|
||||
let somethingChanged = false;
|
||||
const currentTagsSource = state.allElements.getEventSourceById(id);
|
||||
const currentTags = currentTagsSource.data
|
||||
for (const key in latestTags) {
|
||||
let osmValue = latestTags[key]
|
||||
|
||||
if(typeof osmValue === "number"){
|
||||
osmValue = ""+osmValue
|
||||
}
|
||||
|
||||
const localValue = currentTags[key]
|
||||
if (localValue !== osmValue) {
|
||||
console.log("Local value for ", key ,":", localValue, "upstream", osmValue)
|
||||
somethingChanged = true;
|
||||
currentTags[key] = osmValue
|
||||
}
|
||||
}
|
||||
if (somethingChanged) {
|
||||
console.log("Detected upstream changes to the object when opening it, updating...")
|
||||
currentTagsSource.ping()
|
||||
}else{
|
||||
console.debug("Fetched latest tags for ", id, "but detected no changes")
|
||||
}
|
||||
// With the changes applied, we merge them onto the upstream object
|
||||
let somethingChanged = false;
|
||||
const currentTagsSource = state.allElements.getEventSourceById(id);
|
||||
const currentTags = currentTagsSource.data
|
||||
for (const key in latestTags) {
|
||||
let osmValue = latestTags[key]
|
||||
|
||||
if (typeof osmValue === "number") {
|
||||
osmValue = "" + osmValue
|
||||
}
|
||||
|
||||
const localValue = currentTags[key]
|
||||
if (localValue !== osmValue) {
|
||||
console.log("Local value for ", key, ":", localValue, "upstream", osmValue)
|
||||
somethingChanged = true;
|
||||
currentTags[key] = osmValue
|
||||
}
|
||||
}
|
||||
|
||||
for (const currentKey in currentTags) {
|
||||
if (currentKey.startsWith("_")) {
|
||||
continue
|
||||
}
|
||||
if(this.metatags.has(currentKey)){
|
||||
continue
|
||||
}
|
||||
if (currentKey in latestTags) {
|
||||
continue
|
||||
}
|
||||
console.log("Removing key as deleted upstream", currentKey)
|
||||
delete currentTags[currentKey]
|
||||
somethingChanged = true
|
||||
}
|
||||
|
||||
|
||||
if (somethingChanged) {
|
||||
console.log("Detected upstream changes to the object when opening it, updating...")
|
||||
currentTagsSource.ping()
|
||||
} else {
|
||||
console.debug("Fetched latest tags for ", id, "but detected no changes")
|
||||
}
|
||||
} catch (e) {
|
||||
console.error("Updating the tags of selected element ", id, "failed due to", e)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -3,15 +3,20 @@ import {OsmObject} from "../Osm/OsmObject";
|
|||
import Loc from "../../Models/Loc";
|
||||
import {ElementStorage} from "../ElementStorage";
|
||||
import FeaturePipeline from "../FeatureSource/FeaturePipeline";
|
||||
import {GeoOperations} from "../GeoOperations";
|
||||
import LayoutConfig from "../../Models/ThemeConfig/LayoutConfig";
|
||||
|
||||
/**
|
||||
* Makes sure the hash shows the selected element and vice-versa.
|
||||
*/
|
||||
export default class SelectedFeatureHandler {
|
||||
private static readonly _no_trigger_on = new Set(["welcome", "copyright", "layers", "new", "", undefined])
|
||||
hash: UIEventSource<string>;
|
||||
private readonly hash: UIEventSource<string>;
|
||||
private readonly state: {
|
||||
selectedElement: UIEventSource<any>
|
||||
selectedElement: UIEventSource<any>,
|
||||
allElements: ElementStorage,
|
||||
locationControl: UIEventSource<Loc>,
|
||||
layoutToUse: LayoutConfig
|
||||
}
|
||||
|
||||
constructor(
|
||||
|
@ -19,7 +24,9 @@ export default class SelectedFeatureHandler {
|
|||
state: {
|
||||
selectedElement: UIEventSource<any>,
|
||||
allElements: ElementStorage,
|
||||
featurePipeline: FeaturePipeline
|
||||
featurePipeline: FeaturePipeline,
|
||||
locationControl: UIEventSource<Loc>,
|
||||
layoutToUse: LayoutConfig
|
||||
}
|
||||
) {
|
||||
this.hash = hash;
|
||||
|
@ -27,30 +34,9 @@ export default class SelectedFeatureHandler {
|
|||
|
||||
|
||||
// If the hash changes, set the selected element correctly
|
||||
function setSelectedElementFromHash(h){
|
||||
if (h === undefined || h === "") {
|
||||
// Hash has been cleared - we clear the selected element
|
||||
state.selectedElement.setData(undefined);
|
||||
}else{
|
||||
// we search the element to select
|
||||
const feature = state.allElements.ContainingFeatures.get(h)
|
||||
if(feature === undefined){
|
||||
return;
|
||||
}
|
||||
const currentlySeleced = state.selectedElement.data
|
||||
if(currentlySeleced === undefined){
|
||||
state.selectedElement.setData(feature)
|
||||
return;
|
||||
}
|
||||
if(currentlySeleced.properties?.id === feature.properties.id){
|
||||
// We already have the right feature
|
||||
return;
|
||||
}
|
||||
state.selectedElement.setData(feature)
|
||||
}
|
||||
}
|
||||
|
||||
hash.addCallback(setSelectedElementFromHash)
|
||||
const self = this;
|
||||
hash.addCallback(() => self.setSelectedElementFromHash())
|
||||
|
||||
|
||||
// IF the selected element changes, set the hash correctly
|
||||
|
@ -66,41 +52,103 @@ export default class SelectedFeatureHandler {
|
|||
hash.setData(h)
|
||||
}
|
||||
})
|
||||
|
||||
state.featurePipeline.newDataLoadedSignal.addCallbackAndRunD(_ => {
|
||||
|
||||
state.featurePipeline?.newDataLoadedSignal?.addCallbackAndRunD(_ => {
|
||||
// New data was loaded. In initial startup, the hash might be set (via the URL) but might not be selected yet
|
||||
if(hash.data === undefined || SelectedFeatureHandler._no_trigger_on.has(hash.data)){
|
||||
if (hash.data === undefined || SelectedFeatureHandler._no_trigger_on.has(hash.data)) {
|
||||
// This is an invalid hash anyway
|
||||
return;
|
||||
}
|
||||
if(state.selectedElement.data !== undefined){
|
||||
if (state.selectedElement.data !== undefined) {
|
||||
// We already have something selected
|
||||
return;
|
||||
}
|
||||
setSelectedElementFromHash(hash.data)
|
||||
self.setSelectedElementFromHash()
|
||||
})
|
||||
|
||||
|
||||
this.initialLoad()
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* On startup: check if the hash is loaded and eventually zoom to it
|
||||
* @private
|
||||
*/
|
||||
private initialLoad() {
|
||||
const hash = this.hash.data
|
||||
if (hash === undefined || hash === "" || hash.indexOf("-") >= 0) {
|
||||
return;
|
||||
}
|
||||
if (SelectedFeatureHandler._no_trigger_on.has(hash)) {
|
||||
return;
|
||||
}
|
||||
|
||||
OsmObject.DownloadObjectAsync(hash).then(obj => {
|
||||
|
||||
try {
|
||||
|
||||
console.log("Downloaded selected object from OSM-API for initial load: ", hash)
|
||||
const geojson = obj.asGeoJson()
|
||||
this.state.allElements.addOrGetElement(geojson)
|
||||
this.state.selectedElement.setData(geojson)
|
||||
this.zoomToSelectedFeature()
|
||||
} catch (e) {
|
||||
console.error(e)
|
||||
}
|
||||
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
// If a feature is selected via the hash, zoom there
|
||||
public zoomToSelectedFeature(location: UIEventSource<Loc>) {
|
||||
const hash = this.hash.data;
|
||||
if (hash === undefined || SelectedFeatureHandler._no_trigger_on.has(hash)) {
|
||||
return; // No valid feature selected
|
||||
}
|
||||
// We should have a valid osm-ID and zoom to it... But we wrap it in try-catch to be sure
|
||||
try {
|
||||
|
||||
OsmObject.DownloadObject(hash).addCallbackAndRunD(element => {
|
||||
const centerpoint = element.centerpoint();
|
||||
console.log("Zooming to location for select point: ", centerpoint)
|
||||
location.data.lat = centerpoint[0]
|
||||
location.data.lon = centerpoint[1]
|
||||
location.ping();
|
||||
})
|
||||
} catch (e) {
|
||||
console.error("Could not download OSM-object with id", hash, " - probably a weird hash")
|
||||
private setSelectedElementFromHash() {
|
||||
const state = this.state
|
||||
const h = this.hash.data
|
||||
if (h === undefined || h === "") {
|
||||
// Hash has been cleared - we clear the selected element
|
||||
state.selectedElement.setData(undefined);
|
||||
} else {
|
||||
// we search the element to select
|
||||
const feature = state.allElements.ContainingFeatures.get(h)
|
||||
if (feature === undefined) {
|
||||
return;
|
||||
}
|
||||
const currentlySeleced = state.selectedElement.data
|
||||
if (currentlySeleced === undefined) {
|
||||
state.selectedElement.setData(feature)
|
||||
return;
|
||||
}
|
||||
if (currentlySeleced.properties?.id === feature.properties.id) {
|
||||
// We already have the right feature
|
||||
return;
|
||||
}
|
||||
state.selectedElement.setData(feature)
|
||||
}
|
||||
}
|
||||
|
||||
// If a feature is selected via the hash, zoom there
|
||||
private zoomToSelectedFeature() {
|
||||
|
||||
const selected = this.state.selectedElement.data
|
||||
if(selected === undefined){
|
||||
return
|
||||
}
|
||||
|
||||
const centerpoint= GeoOperations.centerpointCoordinates(selected)
|
||||
const location = this.state.locationControl;
|
||||
location.data.lon = centerpoint[0]
|
||||
location.data.lat = centerpoint[1]
|
||||
|
||||
const minZoom = Math.max(14, ...(this.state.layoutToUse?.layers?.map(l => l.minzoomVisible) ?? []))
|
||||
if(location.data.zoom < minZoom ){
|
||||
location.data.zoom = minZoom
|
||||
}
|
||||
|
||||
location.ping();
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -5,6 +5,7 @@ import TagRenderingAnswer from "../../UI/Popup/TagRenderingAnswer";
|
|||
import Combine from "../../UI/Base/Combine";
|
||||
import LayoutConfig from "../../Models/ThemeConfig/LayoutConfig";
|
||||
import {ElementStorage} from "../ElementStorage";
|
||||
import {Utils} from "../../Utils";
|
||||
|
||||
export default class TitleHandler {
|
||||
constructor(state : {
|
||||
|
@ -38,6 +39,9 @@ export default class TitleHandler {
|
|||
|
||||
|
||||
currentTitle.addCallbackAndRunD(title => {
|
||||
if(Utils.runningFromConsole){
|
||||
return
|
||||
}
|
||||
document.title = title
|
||||
})
|
||||
}
|
||||
|
|
|
@ -5,8 +5,6 @@ import State from "../State";
|
|||
import BaseUIElement from "../UI/BaseUIElement";
|
||||
import List from "../UI/Base/List";
|
||||
import Title from "../UI/Base/Title";
|
||||
import {UIEventSourceTools} from "./UIEventSource";
|
||||
import AspectedRouting from "./Osm/aspectedRouting";
|
||||
import {BBox} from "./BBox";
|
||||
|
||||
export interface ExtraFuncParams {
|
||||
|
|
|
@ -21,11 +21,13 @@ export default class AllImageProviders {
|
|||
)
|
||||
|
||||
]
|
||||
|
||||
public static defaultKeys = [].concat(AllImageProviders.ImageAttributionSource.map(provider => provider.defaultKeyPrefixes))
|
||||
|
||||
|
||||
private static _cache: Map<string, UIEventSource<ProvidedImage[]>> = new Map<string, UIEventSource<ProvidedImage[]>>()
|
||||
|
||||
public static LoadImagesFor(tags: UIEventSource<any>, tagKey?: string): UIEventSource<ProvidedImage[]> {
|
||||
public static LoadImagesFor(tags: UIEventSource<any>, tagKey?: string[]): UIEventSource<ProvidedImage[]> {
|
||||
if (tags.data.id === undefined) {
|
||||
return undefined;
|
||||
}
|
||||
|
@ -44,7 +46,7 @@ export default class AllImageProviders {
|
|||
|
||||
let prefixes = imageProvider.defaultKeyPrefixes
|
||||
if(tagKey !== undefined){
|
||||
prefixes = [...prefixes, tagKey]
|
||||
prefixes = tagKey
|
||||
}
|
||||
|
||||
const singleSource = imageProvider.GetRelevantUrls(tags, {
|
||||
|
|
|
@ -27,7 +27,8 @@ export default class ImgurUploader {
|
|||
files,
|
||||
function (url) {
|
||||
console.log("File saved at", url);
|
||||
self.success.setData([...self.success.data, url]);
|
||||
self.success.data.push(url)
|
||||
self.success.ping();
|
||||
self._handleSuccessUrl(url);
|
||||
},
|
||||
function () {
|
||||
|
|
|
@ -1,11 +1,9 @@
|
|||
import ImageProvider, {ProvidedImage} from "./ImageProvider";
|
||||
import BaseUIElement from "../../UI/BaseUIElement";
|
||||
import {UIEventSource} from "../UIEventSource";
|
||||
import Svg from "../../Svg";
|
||||
import {Utils} from "../../Utils";
|
||||
import {LicenseInfo} from "./LicenseInfo";
|
||||
import Constants from "../../Models/Constants";
|
||||
import {fail} from "assert";
|
||||
|
||||
export class Mapillary extends ImageProvider {
|
||||
|
||||
|
@ -13,7 +11,7 @@ export class Mapillary extends ImageProvider {
|
|||
|
||||
public static readonly singleton = new Mapillary();
|
||||
private static readonly valuePrefix = "https://a.mapillary.com"
|
||||
public static readonly valuePrefixes = [Mapillary.valuePrefix, "http://mapillary.com","https://mapillary.com"]
|
||||
public static readonly valuePrefixes = [Mapillary.valuePrefix, "http://mapillary.com","https://mapillary.com","http://www.mapillary.com","https://www.mapillary.com"]
|
||||
|
||||
private static ExtractKeyFromURL(value: string, failIfNoMath = false): {
|
||||
key: string,
|
||||
|
|
|
@ -97,6 +97,7 @@ export class Changes {
|
|||
console.log("Is already uploading... Abort")
|
||||
return;
|
||||
}
|
||||
console.log("Uploading changes due to: ", flushreason)
|
||||
this.isUploading.setData(true)
|
||||
|
||||
this.flushChangesAsync()
|
||||
|
@ -287,7 +288,7 @@ export class Changes {
|
|||
v = undefined;
|
||||
}
|
||||
|
||||
const oldV = obj.type[k]
|
||||
const oldV = obj.tags[k]
|
||||
if (oldV === v) {
|
||||
continue;
|
||||
}
|
||||
|
|
|
@ -8,7 +8,6 @@ import Svg from "../../Svg";
|
|||
import Img from "../../UI/Base/Img";
|
||||
import {Utils} from "../../Utils";
|
||||
import {OsmObject} from "./OsmObject";
|
||||
import LayoutConfig from "../../Models/ThemeConfig/LayoutConfig";
|
||||
import {Changes} from "./Changes";
|
||||
|
||||
export default class UserDetails {
|
||||
|
@ -97,7 +96,6 @@ export class OsmConnection {
|
|||
self.AttemptLogin()
|
||||
}
|
||||
});
|
||||
this.isLoggedIn.addCallbackAndRunD(li => console.log("User is logged in!", li))
|
||||
this._dryRun = options.dryRun;
|
||||
|
||||
this.updateAuthObject();
|
||||
|
|
|
@ -263,7 +263,7 @@ export abstract class OsmObject {
|
|||
continue;
|
||||
}
|
||||
const v = this.tags[key];
|
||||
if (v !== "") {
|
||||
if (v !== "" && v !== undefined) {
|
||||
tags += ' <tag k="' + Utils.EncodeXmlValue(key) + '" v="' + Utils.EncodeXmlValue(this.tags[key]) + '"/>\n'
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,6 +5,7 @@ import LayoutConfig from "../../Models/ThemeConfig/LayoutConfig";
|
|||
import {UIEventSource} from "../UIEventSource";
|
||||
import {QueryParameters} from "../Web/QueryParameters";
|
||||
import Constants from "../../Models/Constants";
|
||||
import {Utils} from "../../Utils";
|
||||
|
||||
export default class FeatureSwitchState {
|
||||
|
||||
|
@ -137,7 +138,7 @@ export default class FeatureSwitchState {
|
|||
|
||||
|
||||
let testingDefaultValue = false;
|
||||
if (this.featureSwitchApiURL.data !== "osm-test" &&
|
||||
if (this.featureSwitchApiURL.data !== "osm-test" && !Utils.runningFromConsole &&
|
||||
(location.hostname === "localhost" || location.hostname === "127.0.0.1")) {
|
||||
testingDefaultValue = true
|
||||
}
|
||||
|
|
|
@ -286,6 +286,9 @@ export class UIEventSource<T> {
|
|||
}
|
||||
|
||||
public stabilized(millisToStabilize): UIEventSource<T> {
|
||||
if(Utils.runningFromConsole){
|
||||
return this;
|
||||
}
|
||||
|
||||
const newSource = new UIEventSource<T>(this.data);
|
||||
|
||||
|
@ -334,21 +337,4 @@ export class UIEventSource<T> {
|
|||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
export class UIEventSourceTools {
|
||||
|
||||
private static readonly _download_cache = new Map<string, UIEventSource<any>>()
|
||||
|
||||
public static downloadJsonCached(url: string): UIEventSource<any> {
|
||||
const cached = UIEventSourceTools._download_cache.get(url)
|
||||
if (cached !== undefined) {
|
||||
return cached;
|
||||
}
|
||||
const src = new UIEventSource<any>(undefined)
|
||||
UIEventSourceTools._download_cache.set(url, src)
|
||||
Utils.downloadJson(url).then(r => src.setData(r))
|
||||
return src;
|
||||
}
|
||||
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue