forked from MapComplete/MapComplete
		
	Also pickup wikimedia categories in the image tags, fix #433
This commit is contained in:
		
							parent
							
								
									8cbb693c98
								
							
						
					
					
						commit
						32cbd6e2c1
					
				
					 6 changed files with 55 additions and 31 deletions
				
			
		|  | @ -5,7 +5,6 @@ import GenericImageProvider from "./GenericImageProvider"; | |||
| import {UIEventSource} from "../UIEventSource"; | ||||
| import ImageProvider, {ProvidedImage} from "./ImageProvider"; | ||||
| import {WikidataImageProvider} from "./WikidataImageProvider"; | ||||
| import {Utils} from "../../Utils"; | ||||
| 
 | ||||
| /** | ||||
|  * A generic 'from the interwebz' image picker, without attribution | ||||
|  | @ -17,12 +16,12 @@ export default class AllImageProviders { | |||
|         Mapillary.singleton, | ||||
|         WikidataImageProvider.singleton, | ||||
|         WikimediaImageProvider.singleton, | ||||
|         new GenericImageProvider(Imgur.defaultValuePrefix)] | ||||
|         new GenericImageProvider([].concat(...Imgur.defaultValuePrefix, WikimediaImageProvider.commonsPrefix))] | ||||
| 
 | ||||
| 
 | ||||
|     private static _cache: Map<string, UIEventSource<ProvidedImage[]>> = new Map<string, UIEventSource<ProvidedImage[]>>() | ||||
| 
 | ||||
|     public static LoadImagesFor(tags: UIEventSource<any>, imagePrefix: string, loadSpecialSource: boolean): UIEventSource<ProvidedImage[]> { | ||||
|     public static LoadImagesFor(tags: UIEventSource<any>, imagePrefix?: string): UIEventSource<ProvidedImage[]> { | ||||
|         const id = tags.data.id | ||||
|         if (id === undefined) { | ||||
|             return undefined; | ||||
|  | @ -33,11 +32,14 @@ export default class AllImageProviders { | |||
|             return cached | ||||
|         } | ||||
| 
 | ||||
| 
 | ||||
|         const source = new UIEventSource([]) | ||||
|         this._cache.set(id, source) | ||||
|         const allSources = [] | ||||
|         for (const imageProvider of AllImageProviders.ImageAttributionSource) { | ||||
|             const singleSource = imageProvider.GetRelevantUrls(tags) | ||||
|             const singleSource = imageProvider.GetRelevantUrls(tags, { | ||||
|                 prefixes: imagePrefix !== undefined ? [imagePrefix] : undefined | ||||
|             }) | ||||
|             allSources.push(singleSource) | ||||
|             singleSource.addCallbackAndRunD(_ => { | ||||
|                 const all : ProvidedImage[] = [].concat(...allSources.map(source => source.data)) | ||||
|  |  | |||
|  | @ -11,12 +11,15 @@ import {LicenseInfo} from "./LicenseInfo"; | |||
| export class WikimediaImageProvider extends ImageProvider { | ||||
| 
 | ||||
| 
 | ||||
|     public readonly defaultKeyPrefixes = ["wikimedia_commons"] | ||||
|     private readonly commons_key = "wikimedia_commons" | ||||
|     public readonly defaultKeyPrefixes = [this.commons_key,"image"] | ||||
|     public static readonly singleton = new WikimediaImageProvider(); | ||||
|     public static readonly commonsPrefix = "https://commons.wikimedia.org/wiki/" | ||||
| 
 | ||||
|     private constructor() { | ||||
|         super(); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Recursively walks a wikimedia commons category in order to search for (image) files | ||||
|      * Returns (a promise of) a list of URLS | ||||
|  | @ -124,38 +127,42 @@ export class WikimediaImageProvider extends ImageProvider { | |||
| 
 | ||||
|     } | ||||
| 
 | ||||
|     private async UrlForImage(image: string): Promise<ProvidedImage>{ | ||||
|         if(!image.startsWith("File:")){ | ||||
|             image = "File:"+image | ||||
|     private async UrlForImage(image: string): Promise<ProvidedImage> { | ||||
|         if (!image.startsWith("File:")) { | ||||
|             image = "File:" + image | ||||
|         } | ||||
|         return {url: this.PrepareUrl(image), key: undefined, provider: this} | ||||
|     } | ||||
|      | ||||
| 
 | ||||
|     public async ExtractUrls(key: string, value: string): Promise<Promise<ProvidedImage>[]> { | ||||
|         const commonsPrefix = "https://commons.wikimedia.org/wiki/" | ||||
|         if(value.startsWith(commonsPrefix)){ | ||||
|             value = value.substring(commonsPrefix.length) | ||||
|         } else       if(value.startsWith("https://upload.wikimedia.org")){ | ||||
|             const result : ProvidedImage = { | ||||
|          | ||||
|         if(key !== this.commons_key && !value.startsWith(WikimediaImageProvider.commonsPrefix)){ | ||||
|             return [] | ||||
|         } | ||||
|          | ||||
|         if (value.startsWith(WikimediaImageProvider.commonsPrefix)) { | ||||
|             value = value.substring(WikimediaImageProvider.commonsPrefix.length) | ||||
|         } else if (value.startsWith("https://upload.wikimedia.org")) { | ||||
|             const result: ProvidedImage = { | ||||
|                 key: undefined, | ||||
|                 url: value, | ||||
|                 provider: this | ||||
|             } | ||||
|             return [Promise.resolve(result)] | ||||
|         } | ||||
|         if(value.startsWith("Category:")){ | ||||
|         if (value.startsWith("Category:")) { | ||||
|             const urls = await WikimediaImageProvider.GetImagesInCategory(value) | ||||
|             return urls.map(image => this.UrlForImage(image)) | ||||
|         } | ||||
|         if(value.startsWith("File:")){ | ||||
|         if (value.startsWith("File:")) { | ||||
|             return [this.UrlForImage(value)] | ||||
|         } | ||||
|         if(value.startsWith("http")){ | ||||
|         if (value.startsWith("http")) { | ||||
|             // PRobably an error
 | ||||
|             return [] | ||||
|         } | ||||
|         // We do a last effort and assume this is a file
 | ||||
|         return [this.UrlForImage("File:"+value)] | ||||
|         return [this.UrlForImage("File:" + value)] | ||||
|     } | ||||
| 
 | ||||
| 
 | ||||
|  |  | |||
|  | @ -42,5 +42,9 @@ export default class FilterConfig { | |||
| 
 | ||||
|             return {question: question, osmTags: osmTags}; | ||||
|         }); | ||||
|          | ||||
|         if(this.options.length > 1 && this.options[0].osmTags["and"]?.length !== 0){ | ||||
|             throw "Error in "+context+"."+this.id+": the first option of a multi-filter should always be the 'reset' option and not have any filters" | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | @ -19,7 +19,6 @@ import CreateNewNodeAction from "../../Logic/Osm/Actions/CreateNewNodeAction"; | |||
| import {OsmObject, OsmWay} from "../../Logic/Osm/OsmObject"; | ||||
| import PresetConfig from "../../Models/ThemeConfig/PresetConfig"; | ||||
| import FilteredLayer from "../../Models/FilteredLayer"; | ||||
| import {And} from "../../Logic/Tags/And"; | ||||
| import {BBox} from "../../Logic/BBox"; | ||||
| 
 | ||||
| /* | ||||
|  | @ -230,7 +229,25 @@ export default class SimpleAddUI extends Toggle { | |||
|         const disableFiltersOrConfirm = new Toggle( | ||||
|             openLayerOrConfirm, | ||||
|             disableFilter, | ||||
|             preset.layerToAddTo.appliedFilters.map(filters => filters === undefined || filters.length === 0) | ||||
|             preset.layerToAddTo.appliedFilters.map(filters => { | ||||
|                 if(filters === undefined || filters.length === 0){ | ||||
|                     return true; | ||||
|                 } | ||||
|                 for (const filter of filters) { | ||||
|                     if(filter.selected === 0 && filter.filter.options.length === 1){ | ||||
|                         return false; | ||||
|                     } | ||||
|                     if(filter.selected !== undefined){ | ||||
|                         const tags = filter.filter.options[filter.selected].osmTags | ||||
|                         if(tags !== undefined && tags["and"]?.length !== 0){ | ||||
|                             // This actually doesn't filter anything at all
 | ||||
|                             return false; | ||||
|                         } | ||||
|                     } | ||||
|                 } | ||||
|                 return true | ||||
|                  | ||||
|             }) | ||||
|         ) | ||||
| 
 | ||||
| 
 | ||||
|  |  | |||
|  | @ -66,16 +66,10 @@ export default class SpecialVisualizations { | |||
|                     name: "image key/prefix", | ||||
|                     defaultValue: "image", | ||||
|                     doc: "The keys given to the images, e.g. if <span class='literal-code'>image</span> is given, the first picture URL will be added as <span class='literal-code'>image</span>, the second as <span class='literal-code'>image:0</span>, the third as <span class='literal-code'>image:1</span>, etc... " | ||||
|                 }, | ||||
|                     { | ||||
|                         name: "smart search", | ||||
|                         defaultValue: "true", | ||||
|                         doc: "Also include images given via 'Wikidata', 'wikimedia_commons' and 'mapillary" | ||||
|                     }], | ||||
|                 }], | ||||
|                 constr: (state: State, tags, args) => { | ||||
|                     const imagePrefix = args[0]; | ||||
|                     const loadSpecial = args[1].toLowerCase() === "true"; | ||||
|                     return new ImageCarousel(AllImageProviders.LoadImagesFor(tags, imagePrefix, loadSpecial), tags); | ||||
|                     return new ImageCarousel(AllImageProviders.LoadImagesFor(tags, imagePrefix), tags); | ||||
|                 } | ||||
|             }, | ||||
|             { | ||||
|  |  | |||
|  | @ -465,9 +465,9 @@ | |||
|             "id": "inside", | ||||
|             "options": [ | ||||
|                 { | ||||
|                     "question": "Binnen of buiten", | ||||
|                     "osmTags": { | ||||
|                         "and": [] | ||||
|                     "question": { | ||||
|                         "nl": "Binnen of buiten", | ||||
|                         "en": "Indoor or outdoor" | ||||
|                     } | ||||
|                 }, | ||||
|                 { | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue