forked from MapComplete/MapComplete
Fix #1794
This commit is contained in:
parent
ad5b5128c0
commit
b8bd13834e
2 changed files with 35 additions and 25 deletions
|
@ -3,7 +3,6 @@ import { MangroveReviews, Review } from "mangrove-reviews-typescript"
|
|||
import { Utils } from "../../Utils"
|
||||
import { Feature, Position } from "geojson"
|
||||
import { GeoOperations } from "../GeoOperations"
|
||||
import ScriptUtils from "../../../scripts/ScriptUtils"
|
||||
|
||||
export class MangroveIdentity {
|
||||
private readonly keypair: UIEventSource<CryptoKeyPair> = new UIEventSource<CryptoKeyPair>(
|
||||
|
@ -28,7 +27,7 @@ export class MangroveIdentity {
|
|||
}
|
||||
|
||||
private async setKeypair(data: string) {
|
||||
console.log("Setting keypair from", data)
|
||||
console.debug("Setting keypair from", data)
|
||||
const keypair = await MangroveReviews.jwkToKeypair(JSON.parse(data))
|
||||
this.keypair.setData(keypair)
|
||||
const pem = await MangroveReviews.publicToPem(keypair.publicKey)
|
||||
|
@ -80,7 +79,6 @@ export class MangroveIdentity {
|
|||
|
||||
public getGeoReviews(): Store<(Review & { kid: string; signature: string })[] | undefined> {
|
||||
if (!this.geoReviewsById) {
|
||||
const all = this.getAllReviews()
|
||||
this.geoReviewsById = this.getAllReviews().mapD((reviews) =>
|
||||
reviews.filter((review) => {
|
||||
try {
|
||||
|
@ -112,12 +110,12 @@ export class MangroveIdentity {
|
|||
return []
|
||||
}
|
||||
const allReviews = await MangroveReviews.getReviews({
|
||||
kid: pem,
|
||||
kid: pem
|
||||
})
|
||||
this.allReviewsById.setData(
|
||||
allReviews.reviews.map((r) => ({
|
||||
...r,
|
||||
...r.payload,
|
||||
...r.payload
|
||||
}))
|
||||
)
|
||||
})
|
||||
|
@ -130,7 +128,9 @@ export class MangroveIdentity {
|
|||
}
|
||||
|
||||
/**
|
||||
* Tracks all reviews of a given feature, allows to create a new review
|
||||
* Tracks all reviews of a given feature, allows to create a new review (and inserts this into the list)
|
||||
*
|
||||
* This object will start fetching the reviews as soon as it is constructed
|
||||
*/
|
||||
export default class FeatureReviews {
|
||||
/**
|
||||
|
@ -169,7 +169,9 @@ export default class FeatureReviews {
|
|||
this._testmode = testmode ?? new ImmutableStore(false)
|
||||
const nameKey = options?.nameKey ?? "name"
|
||||
|
||||
if (feature.geometry.type === "Point") {
|
||||
if (options.uncertaintyRadius) {
|
||||
this._uncertainty = options.uncertaintyRadius
|
||||
} else if (feature.geometry.type === "Point") {
|
||||
this._uncertainty = options?.uncertaintyRadius ?? 10
|
||||
} else {
|
||||
let coordss: Position[][]
|
||||
|
@ -180,6 +182,10 @@ export default class FeatureReviews {
|
|||
feature.geometry.type === "Polygon"
|
||||
) {
|
||||
coordss = feature.geometry.coordinates
|
||||
}else if(feature.geometry.type === "MultiPolygon"){
|
||||
coordss = feature.geometry.coordinates[0]
|
||||
}else{
|
||||
throw "Invalid feature type: "+feature.geometry.type
|
||||
}
|
||||
let maxDistance = 0
|
||||
for (const coords of coordss) {
|
||||
|
@ -191,16 +197,15 @@ export default class FeatureReviews {
|
|||
}
|
||||
}
|
||||
|
||||
this._uncertainty = options?.uncertaintyRadius ?? maxDistance
|
||||
this._uncertainty = maxDistance
|
||||
}
|
||||
this._name = tagsSource.map((tags) => tags[nameKey] ?? options?.fallbackName)
|
||||
|
||||
this.subjectUri = this.ConstructSubjectUri()
|
||||
|
||||
const self = this
|
||||
this.subjectUri.addCallbackAndRunD(async (sub) => {
|
||||
const reviews = await MangroveReviews.getReviews({ sub })
|
||||
self.addReviews(reviews.reviews)
|
||||
this.addReviews(reviews.reviews)
|
||||
})
|
||||
/* We also construct all subject queries _without_ encoding the name to work around a previous bug
|
||||
* See https://github.com/giggls/opencampsitemap/issues/30
|
||||
|
@ -208,7 +213,7 @@ export default class FeatureReviews {
|
|||
this.ConstructSubjectUri(true).addCallbackAndRunD(async (sub) => {
|
||||
try {
|
||||
const reviews = await MangroveReviews.getReviews({ sub })
|
||||
self.addReviews(reviews.reviews)
|
||||
this.addReviews(reviews.reviews)
|
||||
} catch (e) {
|
||||
console.log("Could not fetch reviews for partially incorrect query ", sub)
|
||||
}
|
||||
|
@ -234,6 +239,11 @@ export default class FeatureReviews {
|
|||
|
||||
/**
|
||||
* Construct a featureReviewsFor or fetches it from the cache
|
||||
*
|
||||
* @param feature The feature that we want reviews of. Various properties are used to link reviews to the feature, namely the centerpoint and size and optionally the name
|
||||
* @param tagsSource Dynamic tags of the feature
|
||||
* @param mangroveIdentity Identity with which new REviews will be mad
|
||||
* @param options If options.nameKey is given, this key will be used as subject to fetch reviews
|
||||
*/
|
||||
public static construct(
|
||||
feature: Feature,
|
||||
|
@ -278,7 +288,7 @@ export default class FeatureReviews {
|
|||
}
|
||||
const r: Review = {
|
||||
sub: this.subjectUri.data,
|
||||
...review,
|
||||
...review
|
||||
}
|
||||
const keypair: CryptoKeyPair = await this._identity.getKeypair()
|
||||
const jwt = await MangroveReviews.signReview(keypair, r)
|
||||
|
@ -293,7 +303,7 @@ export default class FeatureReviews {
|
|||
...r,
|
||||
kid,
|
||||
signature: jwt,
|
||||
madeByLoggedInUser: new ImmutableStore(true),
|
||||
madeByLoggedInUser: new ImmutableStore(true)
|
||||
}
|
||||
this._reviews.data.push(reviewWithKid)
|
||||
this._reviews.ping()
|
||||
|
@ -306,8 +316,7 @@ export default class FeatureReviews {
|
|||
* @private
|
||||
*/
|
||||
private addReviews(reviews: { payload: Review; kid: string; signature: string }[]) {
|
||||
const self = this
|
||||
const alreadyKnown = new Set(self._reviews.data.map((r) => r.rating + " " + r.opinion))
|
||||
const alreadyKnown = new Set(this._reviews.data.map((r) => r.rating + " " + r.opinion))
|
||||
|
||||
let hasNew = false
|
||||
for (const reviewData of reviews) {
|
||||
|
@ -335,20 +344,20 @@ export default class FeatureReviews {
|
|||
if (alreadyKnown.has(key)) {
|
||||
continue
|
||||
}
|
||||
self._reviews.data.push({
|
||||
this._reviews.data.push({
|
||||
...review,
|
||||
kid: reviewData.kid,
|
||||
signature: reviewData.signature,
|
||||
madeByLoggedInUser: this._identity.getKeyId().map((user_key_id) => {
|
||||
return reviewData.kid === user_key_id
|
||||
}),
|
||||
})
|
||||
})
|
||||
hasNew = true
|
||||
}
|
||||
if (hasNew) {
|
||||
self._reviews.data.sort((a, b) => b.iat - a.iat) // Sort with most recent first
|
||||
this._reviews.data.sort((a, b) => b.iat - a.iat) // Sort with most recent first
|
||||
|
||||
self._reviews.ping()
|
||||
this._reviews.ping()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -356,16 +365,17 @@ export default class FeatureReviews {
|
|||
* Gets an URI which represents the item in a mangrove-compatible way
|
||||
*
|
||||
* See https://mangrove.reviews/standard#mangrove-core-uri-schemes
|
||||
* @constructor
|
||||
*/
|
||||
private ConstructSubjectUri(dontEncodeName: boolean = false): Store<string> {
|
||||
// https://www.rfc-editor.org/rfc/rfc5870#section-3.4.2
|
||||
// `u` stands for `uncertainty`, https://www.rfc-editor.org/rfc/rfc5870#section-3.4.3
|
||||
const self = this
|
||||
return this._name.map(function (name) {
|
||||
let uri = `geo:${self._lat},${self._lon}?u=${Math.round(self._uncertainty)}`
|
||||
return this._name.map(name => {
|
||||
let uri = `geo:${this._lat},${this._lon}?u=${Math.round(this._uncertainty)}`
|
||||
if (name) {
|
||||
uri += "&q=" + (dontEncodeName ? name : encodeURIComponent(name))
|
||||
}else if(this._uncertainty > 1000){
|
||||
console.error("Not fetching reviews. Only got a point and a very big uncertainty range ("+this._uncertainty+"), so you'd probably only get garbage. Specify a name")
|
||||
return undefined
|
||||
}
|
||||
return uri
|
||||
})
|
||||
|
|
|
@ -651,13 +651,13 @@ console.log(">>> ",helpTexts.join("\n\n"))
|
|||
},
|
||||
{
|
||||
funcName: "rating",
|
||||
docs: "Shows stars which represent the avarage rating on mangrove.reviews",
|
||||
docs: "Shows stars which represent the average rating on mangrove.",
|
||||
needsUrls: [MangroveReviews.ORIGINAL_API],
|
||||
args: [
|
||||
{
|
||||
name: "subjectKey",
|
||||
defaultValue: "name",
|
||||
doc: "The key to use to determine the subject. If specified, the subject will be <b>tags[subjectKey]</b>"
|
||||
doc: "The key to use to determine the subject. If the value is specified, the subject will be <b>tags[subjectKey]</b> and will use this to filter the reviews."
|
||||
},
|
||||
{
|
||||
name: "fallback",
|
||||
|
|
Loading…
Reference in a new issue