forked from MapComplete/MapComplete
		
	Small fixes to link, shows own reviews
This commit is contained in:
		
							parent
							
								
									ef70c17393
								
							
						
					
					
						commit
						0855f46c49
					
				
					 7 changed files with 85 additions and 62 deletions
				
			
		|  | @ -5,6 +5,7 @@ import {Review} from "./Review"; | ||||||
| export class MangroveIdentity { | export class MangroveIdentity { | ||||||
|     private readonly _mangroveIdentity: UIEventSource<string>; |     private readonly _mangroveIdentity: UIEventSource<string>; | ||||||
|     public keypair: any = undefined; |     public keypair: any = undefined; | ||||||
|  |     public readonly kid: UIEventSource<string> = new UIEventSource<string>(undefined); | ||||||
| 
 | 
 | ||||||
|     constructor(mangroveIdentity: UIEventSource<string>) { |     constructor(mangroveIdentity: UIEventSource<string>) { | ||||||
|         const self = this; |         const self = this; | ||||||
|  | @ -13,10 +14,12 @@ export class MangroveIdentity { | ||||||
|             if (str === undefined || str === "") { |             if (str === undefined || str === "") { | ||||||
|                 return; |                 return; | ||||||
|             } |             } | ||||||
|             console.log("JWK ", JSON.parse(str)); |  | ||||||
|             mangrove.jwkToKeypair(JSON.parse(str)).then(keypair => { |             mangrove.jwkToKeypair(JSON.parse(str)).then(keypair => { | ||||||
|                 self.keypair = keypair; |                 self.keypair = keypair; | ||||||
|                 console.log("Identity loaded") |                 mangrove.publicToPem(keypair.publicKey).then(pem => { | ||||||
|  |                     console.log("Identity loaded") | ||||||
|  |                     self.kid.setData(pem); | ||||||
|  |                 }) | ||||||
|             }) |             }) | ||||||
|         }) |         }) | ||||||
|         if ((mangroveIdentity.data ?? "") === "") { |         if ((mangroveIdentity.data ?? "") === "") { | ||||||
|  | @ -117,9 +120,10 @@ export default class MangroveReviews { | ||||||
|                 const reviewsByUser = []; |                 const reviewsByUser = []; | ||||||
|                 for (const review of data.reviews) { |                 for (const review of data.reviews) { | ||||||
|                     const r = review.payload; |                     const r = review.payload; | ||||||
|                     console.log("PublicKey is ",self._mangroveIdentity.keypair, "reviews is",review.signature); | 
 | ||||||
|                     const byUser = self._mangroveIdentity.keypair.publicKey === review.signature; | 
 | ||||||
|                     console.log("IS SAME: ", byUser); |                     console.log("PublicKey is ", self._mangroveIdentity.kid.data, "reviews.kid is", review.kid); | ||||||
|  |                     const byUser = self._mangroveIdentity.kid.map(data => data === review.signature); | ||||||
|                     const rev: Review = { |                     const rev: Review = { | ||||||
|                         made_by_user: byUser, |                         made_by_user: byUser, | ||||||
|                         date: new Date(r.iat * 1000), |                         date: new Date(r.iat * 1000), | ||||||
|  | @ -133,7 +137,7 @@ export default class MangroveReviews { | ||||||
| 
 | 
 | ||||||
|                     (rev.made_by_user ? reviewsByUser : reviews).push(rev); |                     (rev.made_by_user ? reviewsByUser : reviews).push(rev); | ||||||
|                 } |                 } | ||||||
|                 self._reviews.setData(reviews) |                 self._reviews.setData(reviewsByUser.concat(reviews)) | ||||||
|             } |             } | ||||||
|         ); |         ); | ||||||
|         return this._reviews; |         return this._reviews; | ||||||
|  |  | ||||||
|  | @ -1,3 +1,5 @@ | ||||||
|  | import {UIEventSource} from "../UIEventSource"; | ||||||
|  | 
 | ||||||
| export interface Review { | export interface Review { | ||||||
|     comment?: string, |     comment?: string, | ||||||
|     author: string, |     author: string, | ||||||
|  | @ -7,5 +9,5 @@ export interface Review { | ||||||
|     /** |     /** | ||||||
|      * True if the current logged in user is the creator of this comment |      * True if the current logged in user is the creator of this comment | ||||||
|      */ |      */ | ||||||
|     made_by_user: boolean |     made_by_user: UIEventSource<boolean> | ||||||
| } | } | ||||||
|  | @ -4,10 +4,9 @@ | ||||||
| import {UIEventSource} from "../../Logic/UIEventSource"; | import {UIEventSource} from "../../Logic/UIEventSource"; | ||||||
| import {Review} from "../../Logic/Web/Review"; | import {Review} from "../../Logic/Web/Review"; | ||||||
| import {UIElement} from "../UIElement"; | import {UIElement} from "../UIElement"; | ||||||
| import {Utils} from "../../Utils"; |  | ||||||
| import Combine from "../Base/Combine"; | import Combine from "../Base/Combine"; | ||||||
| import {FixedUiElement} from "../Base/FixedUiElement"; |  | ||||||
| import Translations from "../i18n/Translations"; | import Translations from "../i18n/Translations"; | ||||||
|  | import SingleReview from "./SingleReview"; | ||||||
| 
 | 
 | ||||||
| export default class ReviewElement extends UIElement { | export default class ReviewElement extends UIElement { | ||||||
|     private readonly _reviews: UIEventSource<Review[]>; |     private readonly _reviews: UIEventSource<Review[]>; | ||||||
|  | @ -17,37 +16,25 @@ export default class ReviewElement extends UIElement { | ||||||
|     constructor(subject: string, reviews: UIEventSource<Review[]>, middleElement: UIElement) { |     constructor(subject: string, reviews: UIEventSource<Review[]>, middleElement: UIElement) { | ||||||
|         super(reviews); |         super(reviews); | ||||||
|         this._middleElement = middleElement; |         this._middleElement = middleElement; | ||||||
|         if(reviews === undefined){ |         if (reviews === undefined) { | ||||||
|             throw "No reviews UIEVentsource Given!" |             throw "No reviews UIEVentsource Given!" | ||||||
|         } |         } | ||||||
|         this._reviews = reviews; |         this._reviews = reviews; | ||||||
|         this._subject = subject; |         this._subject = subject; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     InnerRender(): string { |  | ||||||
|     |     | ||||||
|         function genStars(rating: number) { | 
 | ||||||
|             if(rating === undefined){ |     InnerRender(): string { | ||||||
|                 return Translations.t.reviews.no_rating; |  | ||||||
|             } |  | ||||||
|             if(rating < 10){ |  | ||||||
|                 rating = 10; |  | ||||||
|             } |  | ||||||
|             const scoreTen = Math.round(rating / 10); |  | ||||||
|             return new Combine([ |  | ||||||
|                 "<img src='./assets/svg/star.svg' />".repeat(Math.floor(scoreTen / 2)), |  | ||||||
|                 scoreTen % 2 == 1 ? "<img src='./assets/svg/star_half.svg' />" : "" |  | ||||||
|             ]) |  | ||||||
|         } |  | ||||||
| 
 | 
 | ||||||
|         const elements = []; |         const elements = []; | ||||||
|         const revs = this._reviews.data; |         const revs = this._reviews.data; | ||||||
|         revs.sort((a,b) => (b.date.getTime() - a.date.getTime())); // Sort with most recent first
 |         revs.sort((a, b) => (b.date.getTime() - a.date.getTime())); // Sort with most recent first
 | ||||||
|         const avg = (revs.map(review => review.rating).reduce((a, b) => a + b, 0) / revs.length); |         const avg = (revs.map(review => review.rating).reduce((a, b) => a + b, 0) / revs.length); | ||||||
|         elements.push( |         elements.push( | ||||||
|             new Combine([ |             new Combine([ | ||||||
|                 genStars(avg).SetClass("stars"), |                 SingleReview.GenStars(avg).SetClass("stars"), | ||||||
|                 `<a href='https://mangrove.reviews/search?sub=${this._subject}'>`, |                 `<a target="_blank" href='https://mangrove.reviews/search?sub=${encodeURIComponent(this._subject)}'>`, | ||||||
|                 Translations.t.reviews.title |                 Translations.t.reviews.title | ||||||
|                     .Subs({count: "" + revs.length}), |                     .Subs({count: "" + revs.length}), | ||||||
|                 "</a>" |                 "</a>" | ||||||
|  | @ -57,29 +44,7 @@ export default class ReviewElement extends UIElement { | ||||||
|          |          | ||||||
|         elements.push(this._middleElement); |         elements.push(this._middleElement); | ||||||
| 
 | 
 | ||||||
|         elements.push(...revs.map(review => { |         elements.push(...revs.map(review => new SingleReview(review))); | ||||||
|             const d = review.date; |  | ||||||
|             return new Combine( |  | ||||||
|                 [ |  | ||||||
|                     new Combine([ |  | ||||||
|                         genStars(review.rating) |  | ||||||
|                             .SetClass("review-rating"), |  | ||||||
|                         new FixedUiElement(review.comment).SetClass("review-comment") |  | ||||||
|                     ]).SetClass("review-stars-comment"), |  | ||||||
| 
 |  | ||||||
|                     new Combine([ |  | ||||||
|                         new Combine([ |  | ||||||
| 
 |  | ||||||
|                             new FixedUiElement(review.author).SetClass("review-author"), |  | ||||||
|                             review.affiliated ? Translations.t.reviews.affiliated_reviewer_warning : "", |  | ||||||
|                         ]).SetStyle("margin-right: 0.5em"), |  | ||||||
|                         new FixedUiElement(`${d.getFullYear()}-${Utils.TwoDigits(d.getMonth() + 1)}-${Utils.TwoDigits(d.getDate())} ${Utils.TwoDigits(d.getHours())}:${Utils.TwoDigits(d.getMinutes())}`) |  | ||||||
|                             .SetClass("review-date") |  | ||||||
|                     ]).SetClass("review-author-date") |  | ||||||
| 
 |  | ||||||
|                 ] |  | ||||||
|             ).SetClass("review-element") |  | ||||||
|         })); |  | ||||||
|         elements.push( |         elements.push( | ||||||
|             new Combine([ |             new Combine([ | ||||||
|                 Translations.t.reviews.attribution, |                 Translations.t.reviews.attribution, | ||||||
|  |  | ||||||
|  | @ -27,7 +27,7 @@ export default class ReviewForm extends InputElement<Review> { | ||||||
|         this.userDetails = userDetails; |         this.userDetails = userDetails; | ||||||
|         const t = Translations.t.reviews; |         const t = Translations.t.reviews; | ||||||
|         this._value  = new UIEventSource({ |         this._value  = new UIEventSource({ | ||||||
|             made_by_user: false, |             made_by_user: new UIEventSource<boolean>(true), | ||||||
|             rating: undefined, |             rating: undefined, | ||||||
|             comment: undefined, |             comment: undefined, | ||||||
|             author: userDetails.data.name, |             author: userDetails.data.name, | ||||||
|  |  | ||||||
|  | @ -1,11 +0,0 @@ | ||||||
| import {UIElement} from "../UIElement"; |  | ||||||
| 
 |  | ||||||
| export default class ReviewPanel extends UIElement { |  | ||||||
|      |  | ||||||
|      |  | ||||||
|      |  | ||||||
|     InnerRender(): string { |  | ||||||
|         return ""; |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
| } |  | ||||||
							
								
								
									
										59
									
								
								UI/Reviews/SingleReview.ts
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										59
									
								
								UI/Reviews/SingleReview.ts
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,59 @@ | ||||||
|  | import {UIElement} from "../UIElement"; | ||||||
|  | import {Review} from "../../Logic/Web/Review"; | ||||||
|  | import Combine from "../Base/Combine"; | ||||||
|  | import {FixedUiElement} from "../Base/FixedUiElement"; | ||||||
|  | import Translations from "../i18n/Translations"; | ||||||
|  | import {Utils} from "../../Utils"; | ||||||
|  | import ReviewElement from "./ReviewElement"; | ||||||
|  | 
 | ||||||
|  | export default class SingleReview extends UIElement{ | ||||||
|  |     private _review: Review; | ||||||
|  |     constructor(review: Review) { | ||||||
|  |         super(review.made_by_user); | ||||||
|  |         this._review = review; | ||||||
|  |        | ||||||
|  |     } | ||||||
|  |     public static GenStars(rating: number): UIElement { | ||||||
|  |         if (rating === undefined) { | ||||||
|  |             return Translations.t.reviews.no_rating; | ||||||
|  |         } | ||||||
|  |         if (rating < 10) { | ||||||
|  |             rating = 10; | ||||||
|  |         } | ||||||
|  |         const scoreTen = Math.round(rating / 10); | ||||||
|  |         return new Combine([ | ||||||
|  |             "<img src='./assets/svg/star.svg' />".repeat(Math.floor(scoreTen / 2)), | ||||||
|  |             scoreTen % 2 == 1 ? "<img src='./assets/svg/star_half.svg' />" : "" | ||||||
|  |         ]) | ||||||
|  |     } | ||||||
|  |     InnerRender(): string { | ||||||
|  |         const d = this._review.date; | ||||||
|  |         let review = this._review; | ||||||
|  |         const el=  new Combine( | ||||||
|  |             [ | ||||||
|  |                 new Combine([ | ||||||
|  |                   SingleReview.GenStars(review.rating) | ||||||
|  |                         .SetClass("review-rating"), | ||||||
|  |                     new FixedUiElement(review.comment).SetClass("review-comment") | ||||||
|  |                 ]).SetClass("review-stars-comment"), | ||||||
|  | 
 | ||||||
|  |                 new Combine([ | ||||||
|  |                     new Combine([ | ||||||
|  | 
 | ||||||
|  |                         new FixedUiElement(review.author).SetClass("review-author"), | ||||||
|  |                         review.affiliated ? Translations.t.reviews.affiliated_reviewer_warning : "", | ||||||
|  |                     ]).SetStyle("margin-right: 0.5em"), | ||||||
|  |                     new FixedUiElement(`${d.getFullYear()}-${Utils.TwoDigits(d.getMonth() + 1)}-${Utils.TwoDigits(d.getDate())} ${Utils.TwoDigits(d.getHours())}:${Utils.TwoDigits(d.getMinutes())}`) | ||||||
|  |                         .SetClass("review-date") | ||||||
|  |                 ]).SetClass("review-author-date") | ||||||
|  | 
 | ||||||
|  |             ] | ||||||
|  |         ); | ||||||
|  |         el.SetClass("review-element"); | ||||||
|  |         if(review.made_by_user){ | ||||||
|  |             el.SetClass("review-by-current-user") | ||||||
|  |         } | ||||||
|  |         return el.Render(); | ||||||
|  |     } | ||||||
|  |      | ||||||
|  | } | ||||||
|  | @ -23,6 +23,10 @@ | ||||||
|     height: 1em; |     height: 1em; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | .review-by-current-user { | ||||||
|  |     border: 5px solid var(--catch-detail-color); | ||||||
|  | } | ||||||
|  | 
 | ||||||
| .review-rating { | .review-rating { | ||||||
|     display: flex; |     display: flex; | ||||||
|     flex-direction: row; |     flex-direction: row; | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue