forked from MapComplete/MapComplete
Merge develop
This commit is contained in:
commit
7c5170da15
193 changed files with 4011 additions and 4462 deletions
|
@ -788,7 +788,7 @@ export class GeoOperations {
|
|||
return undefined
|
||||
}
|
||||
return GeoOperations.centerpointCoordinates(feature)
|
||||
case "polygon_centerpoint":
|
||||
case "polygon_centroid":
|
||||
if (feature.geometry.type === "Polygon") {
|
||||
return GeoOperations.centerpointCoordinates(feature)
|
||||
}
|
||||
|
@ -817,7 +817,7 @@ export class GeoOperations {
|
|||
}
|
||||
return undefined
|
||||
default:
|
||||
throw "Unkown location type: " + location
|
||||
throw "Unkown location type: " + location+" for feature "+feature.properties.id
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -10,6 +10,8 @@ import { WikidataImageProvider } from "./WikidataImageProvider"
|
|||
* A generic 'from the interwebz' image picker, without attribution
|
||||
*/
|
||||
export default class AllImageProviders {
|
||||
private static dontLoadFromPrefixes = ["https://photos.app.goo.gl/"]
|
||||
|
||||
public static ImageAttributionSource: ImageProvider[] = [
|
||||
Imgur.singleton,
|
||||
Mapillary.singleton,
|
||||
|
@ -19,7 +21,8 @@ export default class AllImageProviders {
|
|||
[].concat(
|
||||
...Imgur.defaultValuePrefix,
|
||||
...WikimediaImageProvider.commonsPrefixes,
|
||||
...Mapillary.valuePrefixes
|
||||
...Mapillary.valuePrefixes,
|
||||
...AllImageProviders.dontLoadFromPrefixes
|
||||
)
|
||||
),
|
||||
]
|
||||
|
|
|
@ -25,7 +25,7 @@ export default class MetaTagging {
|
|||
>()
|
||||
|
||||
constructor(state: {
|
||||
readonly selectedElementAndLayer: Store<{ feature: Feature; layer: LayerConfig }>
|
||||
readonly selectedElement: Store<Feature>
|
||||
readonly layout: LayoutConfig
|
||||
readonly osmObjectDownloader: OsmObjectDownloader
|
||||
readonly perLayer: ReadonlyMap<string, GeoIndexedStoreForLayer>
|
||||
|
@ -61,7 +61,8 @@ export default class MetaTagging {
|
|||
})
|
||||
}
|
||||
|
||||
state.selectedElementAndLayer.addCallbackAndRunD(({ feature, layer }) => {
|
||||
state.selectedElement.addCallbackAndRunD((feature) => {
|
||||
const layer = state.layout.getMatchingLayer(feature.properties)
|
||||
// Force update the tags of the currently selected element
|
||||
MetaTagging.addMetatags(
|
||||
[feature],
|
||||
|
|
|
@ -114,7 +114,8 @@ export default class UserRelatedState {
|
|||
)
|
||||
|
||||
this.mangroveIdentity = new MangroveIdentity(
|
||||
this.osmConnection.GetLongPreference("identity", "mangrove")
|
||||
this.osmConnection.GetLongPreference("identity", "mangrove"),
|
||||
this.osmConnection.GetPreference("identity-creation-date", "mangrove")
|
||||
)
|
||||
this.preferredBackgroundLayer = this.osmConnection.GetPreference(
|
||||
"preferred-background-layer",
|
||||
|
@ -364,7 +365,7 @@ export default class UserRelatedState {
|
|||
[translationMode]
|
||||
)
|
||||
|
||||
this.mangroveIdentity.getKeyId().addCallbackAndRun(kid => {
|
||||
this.mangroveIdentity.getKeyId().addCallbackAndRun((kid) => {
|
||||
amendedPrefs.data["mangrove_kid"] = kid
|
||||
amendedPrefs.ping()
|
||||
})
|
||||
|
|
|
@ -432,6 +432,6 @@ export class And extends TagsFilter {
|
|||
}
|
||||
|
||||
asMapboxExpression(): ExpressionSpecification {
|
||||
return ["all", ...this.and.map(t => t.asMapboxExpression())]
|
||||
return ["all", ...this.and.map((t) => t.asMapboxExpression())]
|
||||
}
|
||||
}
|
||||
|
|
|
@ -13,7 +13,7 @@ export default class ComparingTag implements TagsFilter {
|
|||
key: string,
|
||||
predicate: (value: string | undefined) => boolean,
|
||||
representation: "<" | ">" | "<=" | ">=",
|
||||
boundary: string,
|
||||
boundary: string
|
||||
) {
|
||||
this._key = key
|
||||
this._predicate = predicate
|
||||
|
|
|
@ -291,6 +291,6 @@ export class Or extends TagsFilter {
|
|||
}
|
||||
|
||||
asMapboxExpression(): ExpressionSpecification {
|
||||
return ["any", ...this.or.map(t => t.asMapboxExpression())]
|
||||
return ["any", ...this.or.map((t) => t.asMapboxExpression())]
|
||||
}
|
||||
}
|
||||
|
|
|
@ -360,8 +360,8 @@ export class RegexTag extends TagsFilter {
|
|||
}
|
||||
|
||||
asMapboxExpression(): ExpressionSpecification {
|
||||
if(typeof this.key=== "string" && typeof this.value === "string" ) {
|
||||
return [this.invert ? "!=" : "==", ["get",this.key], this.value]
|
||||
if (typeof this.key === "string" && typeof this.value === "string") {
|
||||
return [this.invert ? "!=" : "==", ["get", this.key], this.value]
|
||||
}
|
||||
throw "TODO"
|
||||
}
|
||||
|
|
|
@ -65,7 +65,7 @@ export class Tag extends TagsFilter {
|
|||
asOverpass(): string[] {
|
||||
if (this.value === "") {
|
||||
// NOT having this key
|
||||
return ["[!\"" + this.key + "\"]"]
|
||||
return ['[!"' + this.key + '"]']
|
||||
}
|
||||
return [`["${this.key}"="${this.value}"]`]
|
||||
}
|
||||
|
@ -83,7 +83,7 @@ export class Tag extends TagsFilter {
|
|||
asHumanString(
|
||||
linkToWiki?: boolean,
|
||||
shorten?: boolean,
|
||||
currentProperties?: Record<string, string>,
|
||||
currentProperties?: Record<string, string>
|
||||
) {
|
||||
let v = this.value
|
||||
if (typeof v !== "string") {
|
||||
|
@ -170,12 +170,7 @@ export class Tag extends TagsFilter {
|
|||
|
||||
asMapboxExpression(): ExpressionSpecification {
|
||||
if (this.value === "") {
|
||||
return [
|
||||
"any",
|
||||
["!", ["has", this.key]],
|
||||
["==", ["get", this.key], ""],
|
||||
]
|
||||
|
||||
return ["any", ["!", ["has", this.key]], ["==", ["get", this.key], ""]]
|
||||
}
|
||||
return ["==", ["get", this.key], this.value]
|
||||
}
|
||||
|
|
|
@ -6,11 +6,16 @@ import { GeoOperations } from "../GeoOperations"
|
|||
|
||||
export class MangroveIdentity {
|
||||
private readonly keypair: Store<CryptoKeyPair>
|
||||
private readonly mangroveIdentity: UIEventSource<string>
|
||||
/**
|
||||
* Same as the one in the user settings
|
||||
*/
|
||||
public readonly mangroveIdentity: UIEventSource<string>
|
||||
private readonly key_id: Store<string>
|
||||
private readonly _mangroveIdentityCreationDate: UIEventSource<string>
|
||||
|
||||
constructor(mangroveIdentity: UIEventSource<string>) {
|
||||
constructor(mangroveIdentity: UIEventSource<string>, mangroveIdentityCreationDate: UIEventSource<string>) {
|
||||
this.mangroveIdentity = mangroveIdentity
|
||||
this._mangroveIdentityCreationDate = mangroveIdentityCreationDate
|
||||
const key_id = new UIEventSource<string>(undefined)
|
||||
this.key_id = key_id
|
||||
const keypairEventSource = new UIEventSource<CryptoKeyPair>(undefined)
|
||||
|
@ -24,8 +29,6 @@ export class MangroveIdentity {
|
|||
const pem = await MangroveReviews.publicToPem(keypair.publicKey)
|
||||
key_id.setData(pem)
|
||||
})
|
||||
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -33,27 +36,28 @@ export class MangroveIdentity {
|
|||
* Is written into the UIEventsource, which was passed into the constructor
|
||||
* @constructor
|
||||
*/
|
||||
private static async CreateIdentity(identity: UIEventSource<string>): Promise<void> {
|
||||
private async CreateIdentity(): Promise<void> {
|
||||
const keypair = await MangroveReviews.generateKeypair()
|
||||
const jwk = await MangroveReviews.keypairToJwk(keypair)
|
||||
if ((identity.data ?? "") !== "") {
|
||||
if ((this.mangroveIdentity.data ?? "") !== "") {
|
||||
// Identity has been loaded via osmPreferences by now - we don't overwrite
|
||||
return
|
||||
}
|
||||
console.log("Creating a new Mangrove identity!")
|
||||
identity.setData(JSON.stringify(jwk))
|
||||
this.mangroveIdentity.setData(JSON.stringify(jwk))
|
||||
this._mangroveIdentityCreationDate.setData(new Date().toISOString())
|
||||
}
|
||||
|
||||
/**
|
||||
* Only called to create a review.
|
||||
*/
|
||||
async getKeypair(): Promise<CryptoKeyPair> {
|
||||
if(this.keypair.data ?? "" === ""){
|
||||
if (this.keypair.data ?? "" === "") {
|
||||
// We want to create a review, but it seems like no key has been setup at this moment
|
||||
// We create the key
|
||||
try {
|
||||
if (!Utils.runningFromConsole && (this.mangroveIdentity.data ?? "") === "") {
|
||||
await MangroveIdentity.CreateIdentity(this.mangroveIdentity)
|
||||
await this.CreateIdentity()
|
||||
}
|
||||
} catch (e) {
|
||||
console.error("Could not create identity: ", e)
|
||||
|
@ -66,33 +70,36 @@ export class MangroveIdentity {
|
|||
return this.key_id
|
||||
}
|
||||
|
||||
private allReviewsById : UIEventSource<(Review & {kid: string, signature: string})[]>= undefined
|
||||
|
||||
private allReviewsById: UIEventSource<(Review & { kid: string; signature: string })[]> =
|
||||
undefined
|
||||
|
||||
/**
|
||||
* Gets all reviews that are made for the current identity.
|
||||
*/
|
||||
public getAllReviews(): Store<(Review & {kid: string, signature: string})[]>{
|
||||
if(this.allReviewsById !== undefined){
|
||||
public getAllReviews(): Store<(Review & { kid: string; signature: string })[]> {
|
||||
if (this.allReviewsById !== undefined) {
|
||||
return this.allReviewsById
|
||||
}
|
||||
this.allReviewsById = new UIEventSource( [])
|
||||
this.key_id.map(pem => {
|
||||
if(pem === undefined){
|
||||
this.allReviewsById = new UIEventSource([])
|
||||
this.key_id.map((pem) => {
|
||||
if (pem === undefined) {
|
||||
return []
|
||||
}
|
||||
MangroveReviews.getReviews({
|
||||
kid: pem
|
||||
}).then(allReviews => {
|
||||
this.allReviewsById.setData(allReviews.reviews.map(r => ({
|
||||
...r, ...r.payload
|
||||
})))
|
||||
kid: pem,
|
||||
}).then((allReviews) => {
|
||||
this.allReviewsById.setData(
|
||||
allReviews.reviews.map((r) => ({
|
||||
...r,
|
||||
...r.payload,
|
||||
}))
|
||||
)
|
||||
})
|
||||
})
|
||||
return this.allReviewsById
|
||||
}
|
||||
|
||||
addReview(review: Review & {kid, signature}) {
|
||||
addReview(review: Review & { kid; signature }) {
|
||||
this.allReviewsById?.setData(this.allReviewsById?.data?.concat([review]))
|
||||
}
|
||||
}
|
||||
|
@ -122,7 +129,7 @@ export default class FeatureReviews {
|
|||
private constructor(
|
||||
feature: Feature,
|
||||
tagsSource: UIEventSource<Record<string, string>>,
|
||||
mangroveIdentity?: MangroveIdentity,
|
||||
mangroveIdentity: MangroveIdentity,
|
||||
options?: {
|
||||
nameKey?: "name" | string
|
||||
fallbackName?: string
|
||||
|
@ -131,8 +138,7 @@ export default class FeatureReviews {
|
|||
) {
|
||||
const centerLonLat = GeoOperations.centerpointCoordinates(feature)
|
||||
;[this._lon, this._lat] = centerLonLat
|
||||
this._identity =
|
||||
mangroveIdentity ?? new MangroveIdentity(new UIEventSource<string>(undefined))
|
||||
this._identity = mangroveIdentity
|
||||
const nameKey = options?.nameKey ?? "name"
|
||||
|
||||
if (feature.geometry.type === "Point") {
|
||||
|
@ -225,8 +231,15 @@ export default class FeatureReviews {
|
|||
* The given review is uploaded to mangrove.reviews and added to the list of known reviews
|
||||
*/
|
||||
public async createReview(review: Omit<Review, "sub">): Promise<void> {
|
||||
if(review.opinion !== undefined && review.opinion.length > FeatureReviews .REVIEW_OPINION_MAX_LENGTH){
|
||||
throw "Opinion too long, should be at most "+FeatureReviews.REVIEW_OPINION_MAX_LENGTH+" characters long"
|
||||
if (
|
||||
review.opinion !== undefined &&
|
||||
review.opinion.length > FeatureReviews.REVIEW_OPINION_MAX_LENGTH
|
||||
) {
|
||||
throw (
|
||||
"Opinion too long, should be at most " +
|
||||
FeatureReviews.REVIEW_OPINION_MAX_LENGTH +
|
||||
" characters long"
|
||||
)
|
||||
}
|
||||
const r: Review = {
|
||||
sub: this.subjectUri.data,
|
||||
|
@ -242,13 +255,11 @@ export default class FeatureReviews {
|
|||
signature: jwt,
|
||||
madeByLoggedInUser: new ImmutableStore(true),
|
||||
}
|
||||
this._reviews.data.push( reviewWithKid)
|
||||
this._reviews.data.push(reviewWithKid)
|
||||
this._reviews.ping()
|
||||
this._identity.addReview(reviewWithKid)
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Adds given reviews to the 'reviews'-UI-eventsource
|
||||
* @param reviews
|
||||
|
|
|
@ -115,7 +115,6 @@ export default class ThemeViewStateHashActor {
|
|||
""
|
||||
)
|
||||
selectedElement.setData(found)
|
||||
state.selectedLayer.setData(layer)
|
||||
return true
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue