diff --git a/src/Logic/Web/MangroveReviews.ts b/src/Logic/Web/MangroveReviews.ts index c5332131b..a6c292cb1 100644 --- a/src/Logic/Web/MangroveReviews.ts +++ b/src/Logic/Web/MangroveReviews.ts @@ -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 = new UIEventSource( @@ -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 { // 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 }) diff --git a/src/UI/SpecialVisualizations.ts b/src/UI/SpecialVisualizations.ts index d678393d8..c6dbc72f1 100644 --- a/src/UI/SpecialVisualizations.ts +++ b/src/UI/SpecialVisualizations.ts @@ -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 tags[subjectKey]" + doc: "The key to use to determine the subject. If the value is specified, the subject will be tags[subjectKey] and will use this to filter the reviews." }, { name: "fallback",