forked from MapComplete/MapComplete
Fix tests
This commit is contained in:
parent
064f87537f
commit
d036350893
2 changed files with 61 additions and 59 deletions
|
@ -593,8 +593,9 @@ export default class SimpleMetaTaggers {
|
||||||
(feature: Feature, layer: LayerConfig, tagsStore: UIEventSource<OsmTags>) => {
|
(feature: Feature, layer: LayerConfig, tagsStore: UIEventSource<OsmTags>) => {
|
||||||
Utils.AddLazyPropertyAsync(feature.properties, "_currency", async () => {
|
Utils.AddLazyPropertyAsync(feature.properties, "_currency", async () => {
|
||||||
// Wait until _country is actually set
|
// Wait until _country is actually set
|
||||||
await tagsStore.AsPromise((tags) => !!tags._country)
|
const tags = await tagsStore.AsPromise((tags) => !!tags._country)
|
||||||
|
|
||||||
|
const country = tags._country
|
||||||
// Initialize a list of currencies
|
// Initialize a list of currencies
|
||||||
const currencies = {}
|
const currencies = {}
|
||||||
// Check if there are any currency:XXX tags, add them to the map
|
// Check if there are any currency:XXX tags, add them to the map
|
||||||
|
@ -609,7 +610,7 @@ export default class SimpleMetaTaggers {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Determine the default currency for the country
|
// Determine the default currency for the country
|
||||||
const defaultCurrency = countryToCurrency[feature.properties._country.toUpperCase()]
|
const defaultCurrency = countryToCurrency[country.toUpperCase()]
|
||||||
|
|
||||||
// If the default currency is not in the list, add it
|
// If the default currency is not in the list, add it
|
||||||
if (defaultCurrency && !currencies[defaultCurrency]) {
|
if (defaultCurrency && !currencies[defaultCurrency]) {
|
||||||
|
|
|
@ -255,8 +255,12 @@ export abstract class Store<T> implements Readable<T> {
|
||||||
resolve(data)
|
resolve(data)
|
||||||
} else {
|
} else {
|
||||||
self.addCallbackD((data) => {
|
self.addCallbackD((data) => {
|
||||||
resolve(data)
|
if (condition(data)) {
|
||||||
return true // return true to unregister as we only need to be called once
|
resolve(data)
|
||||||
|
return true // return true to unregister as we only need to be called once
|
||||||
|
} else {
|
||||||
|
return false // We didn't resolve yet, wait for the next ping
|
||||||
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
@ -279,13 +283,13 @@ export abstract class Store<T> implements Readable<T> {
|
||||||
export class ImmutableStore<T> extends Store<T> {
|
export class ImmutableStore<T> extends Store<T> {
|
||||||
public readonly data: T
|
public readonly data: T
|
||||||
|
|
||||||
private static readonly pass: () => void = () => {}
|
|
||||||
|
|
||||||
constructor(data: T) {
|
constructor(data: T) {
|
||||||
super()
|
super()
|
||||||
this.data = data
|
this.data = data
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static readonly pass: () => void = () => {}
|
||||||
|
|
||||||
addCallback(_: (data: T) => void): () => void {
|
addCallback(_: (data: T) => void): () => void {
|
||||||
// pass: data will never change
|
// pass: data will never change
|
||||||
return ImmutableStore.pass
|
return ImmutableStore.pass
|
||||||
|
@ -322,9 +326,9 @@ export class ImmutableStore<T> extends Store<T> {
|
||||||
* Keeps track of the callback functions
|
* Keeps track of the callback functions
|
||||||
*/
|
*/
|
||||||
class ListenerTracker<T> {
|
class ListenerTracker<T> {
|
||||||
|
public pingCount = 0
|
||||||
private readonly _callbacks: ((t: T) => boolean | void | any)[] = []
|
private readonly _callbacks: ((t: T) => boolean | void | any)[] = []
|
||||||
|
|
||||||
public pingCount = 0
|
|
||||||
/**
|
/**
|
||||||
* Adds a callback which can be called; a function to unregister is returned
|
* Adds a callback which can be called; a function to unregister is returned
|
||||||
*/
|
*/
|
||||||
|
@ -386,18 +390,16 @@ class ListenerTracker<T> {
|
||||||
* The mapped store is a helper type which does the mapping of a function.
|
* The mapped store is a helper type which does the mapping of a function.
|
||||||
*/
|
*/
|
||||||
class MappedStore<TIn, T> extends Store<T> {
|
class MappedStore<TIn, T> extends Store<T> {
|
||||||
|
private static readonly pass: () => {}
|
||||||
private readonly _upstream: Store<TIn>
|
private readonly _upstream: Store<TIn>
|
||||||
private readonly _upstreamCallbackHandler: ListenerTracker<TIn> | undefined
|
private readonly _upstreamCallbackHandler: ListenerTracker<TIn> | undefined
|
||||||
private _upstreamPingCount: number = -1
|
private _upstreamPingCount: number = -1
|
||||||
private _unregisterFromUpstream: () => void
|
private _unregisterFromUpstream: () => void
|
||||||
|
|
||||||
private readonly _f: (t: TIn) => T
|
private readonly _f: (t: TIn) => T
|
||||||
private readonly _extraStores: Store<any>[] | undefined
|
private readonly _extraStores: Store<any>[] | undefined
|
||||||
private _unregisterFromExtraStores: (() => void)[] | undefined
|
private _unregisterFromExtraStores: (() => void)[] | undefined
|
||||||
|
|
||||||
private _callbacks: ListenerTracker<T> = new ListenerTracker<T>()
|
private _callbacks: ListenerTracker<T> = new ListenerTracker<T>()
|
||||||
|
private _callbacksAreRegistered = false
|
||||||
private static readonly pass: () => {}
|
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
upstream: Store<TIn>,
|
upstream: Store<TIn>,
|
||||||
|
@ -421,7 +423,6 @@ class MappedStore<TIn, T> extends Store<T> {
|
||||||
}
|
}
|
||||||
|
|
||||||
private _data: T
|
private _data: T
|
||||||
private _callbacksAreRegistered = false
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the current data from the store
|
* Gets the current data from the store
|
||||||
|
@ -468,33 +469,6 @@ class MappedStore<TIn, T> extends Store<T> {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
private unregisterFromUpstream() {
|
|
||||||
console.log("Unregistering callbacks for", this.tag)
|
|
||||||
this._callbacksAreRegistered = false
|
|
||||||
this._unregisterFromUpstream()
|
|
||||||
this._unregisterFromExtraStores?.forEach((unr) => unr())
|
|
||||||
}
|
|
||||||
|
|
||||||
private registerCallbacksToUpstream() {
|
|
||||||
const self = this
|
|
||||||
|
|
||||||
this._unregisterFromUpstream = this._upstream.addCallback((_) => self.update())
|
|
||||||
this._unregisterFromExtraStores = this._extraStores?.map((store) =>
|
|
||||||
store?.addCallback((_) => self.update())
|
|
||||||
)
|
|
||||||
this._callbacksAreRegistered = true
|
|
||||||
}
|
|
||||||
|
|
||||||
private update(): void {
|
|
||||||
const newData = this._f(this._upstream.data)
|
|
||||||
this._upstreamPingCount = this._upstreamCallbackHandler?.pingCount
|
|
||||||
if (this._data == newData) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
this._data = newData
|
|
||||||
this._callbacks.ping(this._data)
|
|
||||||
}
|
|
||||||
|
|
||||||
addCallback(callback: (data: T) => any | boolean | void): () => void {
|
addCallback(callback: (data: T) => any | boolean | void): () => void {
|
||||||
if (!this._callbacksAreRegistered) {
|
if (!this._callbacksAreRegistered) {
|
||||||
// This is the first callback that is added
|
// This is the first callback that is added
|
||||||
|
@ -535,14 +509,40 @@ class MappedStore<TIn, T> extends Store<T> {
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private unregisterFromUpstream() {
|
||||||
|
console.log("Unregistering callbacks for", this.tag)
|
||||||
|
this._callbacksAreRegistered = false
|
||||||
|
this._unregisterFromUpstream()
|
||||||
|
this._unregisterFromExtraStores?.forEach((unr) => unr())
|
||||||
|
}
|
||||||
|
|
||||||
|
private registerCallbacksToUpstream() {
|
||||||
|
const self = this
|
||||||
|
|
||||||
|
this._unregisterFromUpstream = this._upstream.addCallback((_) => self.update())
|
||||||
|
this._unregisterFromExtraStores = this._extraStores?.map((store) =>
|
||||||
|
store?.addCallback((_) => self.update())
|
||||||
|
)
|
||||||
|
this._callbacksAreRegistered = true
|
||||||
|
}
|
||||||
|
|
||||||
|
private update(): void {
|
||||||
|
const newData = this._f(this._upstream.data)
|
||||||
|
this._upstreamPingCount = this._upstreamCallbackHandler?.pingCount
|
||||||
|
if (this._data == newData) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
this._data = newData
|
||||||
|
this._callbacks.ping(this._data)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export class UIEventSource<T> extends Store<T> implements Writable<T> {
|
export class UIEventSource<T> extends Store<T> implements Writable<T> {
|
||||||
|
private static readonly pass: () => {}
|
||||||
public data: T
|
public data: T
|
||||||
_callbacks: ListenerTracker<T> = new ListenerTracker<T>()
|
_callbacks: ListenerTracker<T> = new ListenerTracker<T>()
|
||||||
|
|
||||||
private static readonly pass: () => {}
|
|
||||||
|
|
||||||
constructor(data: T, tag: string = "") {
|
constructor(data: T, tag: string = "") {
|
||||||
super(tag)
|
super(tag)
|
||||||
this.data = data
|
this.data = data
|
||||||
|
@ -624,6 +624,24 @@ export class UIEventSource<T> extends Store<T> implements Writable<T> {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static asBoolean(stringUIEventSource: UIEventSource<string>) {
|
||||||
|
return stringUIEventSource.sync(
|
||||||
|
(str) => str === "true",
|
||||||
|
[],
|
||||||
|
(b) => "" + b
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new UIEVentSource. Whenever 'source' changes, the returned UIEventSource will get this value as well.
|
||||||
|
* However, this value can be overriden without affecting source
|
||||||
|
*/
|
||||||
|
static feedFrom<T>(store: Store<T>): UIEventSource<T> {
|
||||||
|
const src = new UIEventSource(store.data)
|
||||||
|
store.addCallback((t) => src.setData(t))
|
||||||
|
return src
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adds a callback
|
* Adds a callback
|
||||||
*
|
*
|
||||||
|
@ -704,6 +722,7 @@ export class UIEventSource<T> extends Store<T> implements Writable<T> {
|
||||||
): Store<J> {
|
): Store<J> {
|
||||||
return new MappedStore(this, f, extraSources, this._callbacks, f(this.data), onDestroy)
|
return new MappedStore(this, f, extraSources, this._callbacks, f(this.data), onDestroy)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Monoidal map which results in a read-only store. 'undefined' is passed 'as is'
|
* Monoidal map which results in a read-only store. 'undefined' is passed 'as is'
|
||||||
* Given a function 'f', will construct a new UIEventSource where the contents will always be "f(this.data)'
|
* Given a function 'f', will construct a new UIEventSource where the contents will always be "f(this.data)'
|
||||||
|
@ -779,14 +798,6 @@ export class UIEventSource<T> extends Store<T> implements Writable<T> {
|
||||||
return this
|
return this
|
||||||
}
|
}
|
||||||
|
|
||||||
static asBoolean(stringUIEventSource: UIEventSource<string>) {
|
|
||||||
return stringUIEventSource.sync(
|
|
||||||
(str) => str === "true",
|
|
||||||
[],
|
|
||||||
(b) => "" + b
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
set(value: T): void {
|
set(value: T): void {
|
||||||
this.setData(value)
|
this.setData(value)
|
||||||
}
|
}
|
||||||
|
@ -794,14 +805,4 @@ export class UIEventSource<T> extends Store<T> implements Writable<T> {
|
||||||
update(f: Updater<T> & ((value: T) => T)): void {
|
update(f: Updater<T> & ((value: T) => T)): void {
|
||||||
this.setData(f(this.data))
|
this.setData(f(this.data))
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Create a new UIEVentSource. Whenever 'source' changes, the returned UIEventSource will get this value as well.
|
|
||||||
* However, this value can be overriden without affecting source
|
|
||||||
*/
|
|
||||||
static feedFrom<T>(store: Store<T>): UIEventSource<T> {
|
|
||||||
const src = new UIEventSource(store.data)
|
|
||||||
store.addCallback((t) => src.setData(t))
|
|
||||||
return src
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue