forked from MapComplete/MapComplete
		
	Themes: don't do face blurring for some layers (artwork, memorials, ghost_bikes)
This commit is contained in:
		
							parent
							
								
									7d83cb1a7f
								
							
						
					
					
						commit
						15176a1682
					
				
					 11 changed files with 370 additions and 342 deletions
				
			
		|  | @ -187,7 +187,7 @@ | ||||||
|     } |     } | ||||||
|   ], |   ], | ||||||
|   "tagRenderings": [ |   "tagRenderings": [ | ||||||
|     "images", |     "images_no_blur", | ||||||
|     { |     { | ||||||
|       "labels": [ |       "labels": [ | ||||||
|         "artwork-question" |         "artwork-question" | ||||||
|  |  | ||||||
|  | @ -142,7 +142,7 @@ | ||||||
|   ], |   ], | ||||||
|   "tagRenderings": [ |   "tagRenderings": [ | ||||||
|     "preset_description", |     "preset_description", | ||||||
|     "images", |     "images_no_blur", | ||||||
|     { |     { | ||||||
|       "question": { |       "question": { | ||||||
|         "en": "Whom is remembered by this ghost bike?", |         "en": "Whom is remembered by this ghost bike?", | ||||||
|  |  | ||||||
|  | @ -91,7 +91,7 @@ | ||||||
|     } |     } | ||||||
|   ], |   ], | ||||||
|   "tagRenderings": [ |   "tagRenderings": [ | ||||||
|     "images", |     "images_no_blur", | ||||||
|     { |     { | ||||||
|       "id": "memorial-type", |       "id": "memorial-type", | ||||||
|       "labels": [ |       "labels": [ | ||||||
|  |  | ||||||
|  | @ -19,6 +19,13 @@ | ||||||
|         "*": "{image_carousel()}{image_upload()}" |         "*": "{image_carousel()}{image_upload()}" | ||||||
|       } |       } | ||||||
|     }, |     }, | ||||||
|  |     { | ||||||
|  |       "id": "images_no_blur", | ||||||
|  |       "description": "Same as `images`, but uploaded request to disable blurring to the panoramax server", | ||||||
|  |       "render": { | ||||||
|  |         "*": "{image_carousel()}{image_upload(,,,true)}" | ||||||
|  |       } | ||||||
|  |     }, | ||||||
|     { |     { | ||||||
|       "id": "mapillary", |       "id": "mapillary", | ||||||
|       "description": "Shows a button to open Mapillary on this location", |       "description": "Shows a button to open Mapillary on this location", | ||||||
|  |  | ||||||
							
								
								
									
										14
									
								
								package-lock.json
									
										
									
										generated
									
									
									
								
							
							
						
						
									
										14
									
								
								package-lock.json
									
										
									
										generated
									
									
									
								
							|  | @ -64,7 +64,7 @@ | ||||||
|         "opening_hours": "^3.6.0", |         "opening_hours": "^3.6.0", | ||||||
|         "osm-auth": "^2.5.0", |         "osm-auth": "^2.5.0", | ||||||
|         "osmtogeojson": "^3.0.0-beta.5", |         "osmtogeojson": "^3.0.0-beta.5", | ||||||
|         "panoramax-js": "^0.3.6", |         "panoramax-js": "^0.3.8", | ||||||
|         "panzoom": "^9.4.3", |         "panzoom": "^9.4.3", | ||||||
|         "papaparse": "^5.3.1", |         "papaparse": "^5.3.1", | ||||||
|         "pg": "^8.11.3", |         "pg": "^8.11.3", | ||||||
|  | @ -16002,9 +16002,9 @@ | ||||||
|       "license": "MIT" |       "license": "MIT" | ||||||
|     }, |     }, | ||||||
|     "node_modules/panoramax-js": { |     "node_modules/panoramax-js": { | ||||||
|       "version": "0.3.6", |       "version": "0.3.8", | ||||||
|       "resolved": "https://registry.npmjs.org/panoramax-js/-/panoramax-js-0.3.6.tgz", |       "resolved": "https://registry.npmjs.org/panoramax-js/-/panoramax-js-0.3.8.tgz", | ||||||
|       "integrity": "sha512-CRdXwh91H6chd1PYptG070ukx+S6IkVaUeQVG91ySevoJoCYOuBT65qkMhRo49X2um1nGcs9UqolW90R57875g==", |       "integrity": "sha512-l8bUi+urcdqLjckGcEyDmYyAYCKjwFXpk/En7gpi5x32Nq2r9sHq7obX3Jbk1F7zH4rmpKbVtjS97cKEZr9zHQ==", | ||||||
|       "dependencies": { |       "dependencies": { | ||||||
|         "@ogcapi-js/features": "^1.1.1", |         "@ogcapi-js/features": "^1.1.1", | ||||||
|         "@ogcapi-js/shared": "^1.1.1", |         "@ogcapi-js/shared": "^1.1.1", | ||||||
|  | @ -32087,9 +32087,9 @@ | ||||||
|       "version": "1.0.0" |       "version": "1.0.0" | ||||||
|     }, |     }, | ||||||
|     "panoramax-js": { |     "panoramax-js": { | ||||||
|       "version": "0.3.6", |       "version": "0.3.8", | ||||||
|       "resolved": "https://registry.npmjs.org/panoramax-js/-/panoramax-js-0.3.6.tgz", |       "resolved": "https://registry.npmjs.org/panoramax-js/-/panoramax-js-0.3.8.tgz", | ||||||
|       "integrity": "sha512-CRdXwh91H6chd1PYptG070ukx+S6IkVaUeQVG91ySevoJoCYOuBT65qkMhRo49X2um1nGcs9UqolW90R57875g==", |       "integrity": "sha512-l8bUi+urcdqLjckGcEyDmYyAYCKjwFXpk/En7gpi5x32Nq2r9sHq7obX3Jbk1F7zH4rmpKbVtjS97cKEZr9zHQ==", | ||||||
|       "requires": { |       "requires": { | ||||||
|         "@ogcapi-js/features": "^1.1.1", |         "@ogcapi-js/features": "^1.1.1", | ||||||
|         "@ogcapi-js/shared": "^1.1.1", |         "@ogcapi-js/shared": "^1.1.1", | ||||||
|  |  | ||||||
|  | @ -208,7 +208,7 @@ | ||||||
|     "opening_hours": "^3.6.0", |     "opening_hours": "^3.6.0", | ||||||
|     "osm-auth": "^2.5.0", |     "osm-auth": "^2.5.0", | ||||||
|     "osmtogeojson": "^3.0.0-beta.5", |     "osmtogeojson": "^3.0.0-beta.5", | ||||||
|     "panoramax-js": "^0.3.6", |     "panoramax-js": "^0.3.8", | ||||||
|     "panzoom": "^9.4.3", |     "panzoom": "^9.4.3", | ||||||
|     "papaparse": "^5.3.1", |     "papaparse": "^5.3.1", | ||||||
|     "pg": "^8.11.3", |     "pg": "^8.11.3", | ||||||
|  |  | ||||||
|  | @ -81,11 +81,10 @@ export class ImageUploadManager { | ||||||
| 
 | 
 | ||||||
|     public canBeUploaded(file: File): true | { error: Translation } { |     public canBeUploaded(file: File): true | { error: Translation } { | ||||||
|         const sizeInBytes = file.size |         const sizeInBytes = file.size | ||||||
|         const self = this |  | ||||||
|         if (sizeInBytes > this._uploader.maxFileSizeInMegabytes * 1000000) { |         if (sizeInBytes > this._uploader.maxFileSizeInMegabytes * 1000000) { | ||||||
|             const error = Translations.t.image.toBig.Subs({ |             const error = Translations.t.image.toBig.Subs({ | ||||||
|                 actual_size: Math.floor(sizeInBytes / 1000000) + "MB", |                 actual_size: Math.floor(sizeInBytes / 1000000) + "MB", | ||||||
|                 max_size: self._uploader.maxFileSizeInMegabytes + "MB", |                 max_size: this._uploader.maxFileSizeInMegabytes + "MB", | ||||||
|             }) |             }) | ||||||
|             return { error } |             return { error } | ||||||
|         } |         } | ||||||
|  | @ -102,7 +101,8 @@ export class ImageUploadManager { | ||||||
|     public async uploadImageAndApply( |     public async uploadImageAndApply( | ||||||
|         file: File, |         file: File, | ||||||
|         tagsStore: UIEventSource<OsmTags>, |         tagsStore: UIEventSource<OsmTags>, | ||||||
|         targetKey?: string, |         targetKey: string, | ||||||
|  |         noblur: boolean, | ||||||
|     ): Promise<void> { |     ): Promise<void> { | ||||||
|         const canBeUploaded = this.canBeUploaded(file) |         const canBeUploaded = this.canBeUploaded(file) | ||||||
|         if (canBeUploaded !== true) { |         if (canBeUploaded !== true) { | ||||||
|  | @ -120,6 +120,7 @@ export class ImageUploadManager { | ||||||
|             author, |             author, | ||||||
|             file, |             file, | ||||||
|             targetKey, |             targetKey, | ||||||
|  |             noblur | ||||||
|         ) |         ) | ||||||
|         if (!uploadResult) { |         if (!uploadResult) { | ||||||
|             return |             return | ||||||
|  | @ -139,6 +140,7 @@ export class ImageUploadManager { | ||||||
|         author: string, |         author: string, | ||||||
|         blob: File, |         blob: File, | ||||||
|         targetKey: string | undefined, |         targetKey: string | undefined, | ||||||
|  |         noblur: boolean | ||||||
|     ): Promise<UploadResult> { |     ): Promise<UploadResult> { | ||||||
|         this.increaseCountFor(this._uploadStarted, featureId) |         this.increaseCountFor(this._uploadStarted, featureId) | ||||||
|         let key: string |         let key: string | ||||||
|  | @ -153,12 +155,12 @@ export class ImageUploadManager { | ||||||
|             location = GeoOperations.centerpointCoordinates(feature) |             location = GeoOperations.centerpointCoordinates(feature) | ||||||
|         } |         } | ||||||
|         try { |         try { | ||||||
|             ;({ key, value, absoluteUrl } = await this._uploader.uploadImage(blob, location, author)) |             ({ key, value, absoluteUrl } = await this._uploader.uploadImage(blob, location, author, noblur)) | ||||||
|         } catch (e) { |         } catch (e) { | ||||||
|             this.increaseCountFor(this._uploadRetried, featureId) |             this.increaseCountFor(this._uploadRetried, featureId) | ||||||
|             console.error("Could not upload image, trying again:", e) |             console.error("Could not upload image, trying again:", e) | ||||||
|             try { |             try { | ||||||
|                 ;({ key, value , absoluteUrl} = await this._uploader.uploadImage(blob, location, author)) |                 ({ key, value , absoluteUrl} = await this._uploader.uploadImage(blob, location, author, noblur)) | ||||||
|                 this.increaseCountFor(this._uploadRetriedSuccess, featureId) |                 this.increaseCountFor(this._uploadRetriedSuccess, featureId) | ||||||
|             } catch (e) { |             } catch (e) { | ||||||
|                 console.error("Could again not upload image due to", e) |                 console.error("Could again not upload image due to", e) | ||||||
|  |  | ||||||
|  | @ -7,7 +7,8 @@ export interface ImageUploader { | ||||||
|     uploadImage( |     uploadImage( | ||||||
|         blob: File, |         blob: File, | ||||||
|         currentGps: [number,number], |         currentGps: [number,number], | ||||||
|         author: string |         author: string, | ||||||
|  |         noblur: boolean | ||||||
|     ): Promise<UploadResult> |     ): Promise<UploadResult> | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -167,12 +167,12 @@ export class PanoramaxUploader implements ImageUploader { | ||||||
|         this._panoramax = new AuthorizedPanoramax(url, token) |         this._panoramax = new AuthorizedPanoramax(url, token) | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     async uploadImage(blob: File, currentGps: [number, number], author: string): Promise<{ |     async uploadImage(blob: File, currentGps: [number, number], author: string,  noblur: boolean = false): Promise<{ | ||||||
|         key: string; |         key: string; | ||||||
|         value: string; |         value: string; | ||||||
|         absoluteUrl: string |         absoluteUrl: string | ||||||
|     }> { |     }> { | ||||||
| 
 |         // https://panoramax.openstreetmap.fr/api/docs/swagger#/
 | ||||||
|         const tags = await ExifReader.load(blob) |         const tags = await ExifReader.load(blob) | ||||||
|         const hasDate = tags.DateTime !== undefined |         const hasDate = tags.DateTime !== undefined | ||||||
|         const hasGPS = tags.GPSLatitude !== undefined && tags.GPSLongitude !== undefined |         const hasGPS = tags.GPSLatitude !== undefined && tags.GPSLongitude !== undefined | ||||||
|  | @ -184,6 +184,7 @@ export class PanoramaxUploader implements ImageUploader { | ||||||
|         const img = <ImageData>await p.addImage(blob, defaultSequence, { |         const img = <ImageData>await p.addImage(blob, defaultSequence, { | ||||||
|             lat: !hasGPS ? lat : undefined, |             lat: !hasGPS ? lat : undefined, | ||||||
|             lon: !hasGPS ? lon : undefined, |             lon: !hasGPS ? lon : undefined, | ||||||
|  |             isBlurred: noblur, | ||||||
|             datetime: !hasDate ? new Date().toISOString() : undefined, |             datetime: !hasDate ? new Date().toISOString() : undefined, | ||||||
|             exifOverride: { |             exifOverride: { | ||||||
|                 Artist: author, |                 Artist: author, | ||||||
|  |  | ||||||
|  | @ -4,8 +4,8 @@ | ||||||
|    */ |    */ | ||||||
| 
 | 
 | ||||||
|   import type { SpecialVisualizationState } from "../SpecialVisualization" |   import type { SpecialVisualizationState } from "../SpecialVisualization" | ||||||
|   import { ImmutableStore, UIEventSource } from "../../Logic/UIEventSource" |   import { UIEventSource } from "../../Logic/UIEventSource" | ||||||
|   import type { OsmId, OsmTags } from "../../Models/OsmFeature" |   import type { OsmTags } from "../../Models/OsmFeature" | ||||||
|   import LoginToggle from "../Base/LoginToggle.svelte" |   import LoginToggle from "../Base/LoginToggle.svelte" | ||||||
|   import Translations from "../i18n/Translations" |   import Translations from "../i18n/Translations" | ||||||
|   import Tr from "../Base/Tr.svelte" |   import Tr from "../Base/Tr.svelte" | ||||||
|  | @ -22,6 +22,7 @@ | ||||||
|   export let tags: UIEventSource<OsmTags> |   export let tags: UIEventSource<OsmTags> | ||||||
|   export let targetKey: string = undefined |   export let targetKey: string = undefined | ||||||
|   export let layer: LayerConfig |   export let layer: LayerConfig | ||||||
|  |   export let noBlur: boolean = false | ||||||
|   /** |   /** | ||||||
|    * Image to show in the button |    * Image to show in the button | ||||||
|    * NOT the image to upload! |    * NOT the image to upload! | ||||||
|  | @ -47,22 +48,22 @@ | ||||||
|           continue |           continue | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         if(layer?.id === "note"){ |         if (layer?.id === "note") { | ||||||
|           const uploadResult = await state?.imageUploadManager.uploadImageWithLicense(tags.data.id, |           const uploadResult = await state?.imageUploadManager.uploadImageWithLicense(tags.data.id, | ||||||
|             state.osmConnection.userDetails.data?.name ?? "Anonymous", |             state.osmConnection.userDetails.data?.name ?? "Anonymous", | ||||||
|             file, "image") |             file, "image", noBlur) | ||||||
|           if(!uploadResult){ |           if (!uploadResult) { | ||||||
|             return |             return | ||||||
|           } |           } | ||||||
|           const url = uploadResult.absoluteUrl |           const url = uploadResult.absoluteUrl | ||||||
|           await state.osmConnection.addCommentToNote(tags.data.id, url) |           await state.osmConnection.addCommentToNote(tags.data.id, url) | ||||||
|           NoteCommentElement.addCommentTo(url, <UIEventSource<any>>tags, { |           NoteCommentElement.addCommentTo(url, <UIEventSource<any>>tags, { | ||||||
|             osmConnection: state.osmConnection, |             osmConnection: state.osmConnection | ||||||
|           }) |           }) | ||||||
|           return |           return | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         await state?.imageUploadManager.uploadImageAndApply(file, tags, targetKey) |         await state?.imageUploadManager.uploadImageAndApply(file, tags, targetKey, noBlur) | ||||||
|       } catch (e) { |       } catch (e) { | ||||||
|         console.error(e) |         console.error(e) | ||||||
|         state.reportError(e, "Could not upload image") |         state.reportError(e, "Could not upload image") | ||||||
|  | @ -96,12 +97,21 @@ | ||||||
|         {#if labelText} |         {#if labelText} | ||||||
|           {labelText} |           {labelText} | ||||||
|         {:else} |         {:else} | ||||||
|  |           <div class="flex flex-col"> | ||||||
|  | 
 | ||||||
|             <Tr t={t.addPicture} /> |             <Tr t={t.addPicture} /> | ||||||
|  |             {#if noBlur} | ||||||
|  |           <span class="subtle text-sm"> | ||||||
|  |           Faces will not be blurred | ||||||
|  |           </span> | ||||||
|             {/if} |             {/if} | ||||||
|           </div> |           </div> | ||||||
|  |         {/if} | ||||||
|  | 
 | ||||||
|  |       </div> | ||||||
|     </FileSelector> |     </FileSelector> | ||||||
|     <div class="text-xs subtle italic"> |     <div class="text-xs subtle italic"> | ||||||
|       <Tr t={Translations.t.general.attribution.panoramaxLicenseCCBYSA}/> |       <Tr t={Translations.t.general.attribution.panoramaxLicenseCCBYSA} /> | ||||||
|       <span class="mx-1">—</span> |       <span class="mx-1">—</span> | ||||||
|       <Tr t={t.respectPrivacy} /> |       <Tr t={t.respectPrivacy} /> | ||||||
|     </div> |     </div> | ||||||
|  |  | ||||||
										
											
												File diff suppressed because it is too large
												Load diff
											
										
									
								
							
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue