import { SpecialVisualizationState, SpecialVisualizationSvelte } from "../SpecialVisualization" import AllImageProviders from "../../Logic/ImageProviders/AllImageProviders" import SvelteUIElement from "../Base/SvelteUIElement" import ImageCarousel from "../Image/ImageCarousel.svelte" import UploadImage from "../Image/UploadImage.svelte" import { CombinedFetcher } from "../../Logic/Web/NearbyImagesSearch" import { UIEventSource } from "../../Logic/UIEventSource" import { Feature } from "geojson" import LayerConfig from "../../Models/ThemeConfig/LayerConfig" import { GeoOperations } from "../../Logic/GeoOperations" import NearbyImages from "../Image/NearbyImages.svelte" import NearbyImagesCollapsed from "../Image/NearbyImagesCollapsed.svelte" import Constants from "../../Models/Constants" class NearbyImageVis extends SpecialVisualizationSvelte { // Class must be in SpecialVisualisations due to weird cyclical import that breaks the tests args = [ { name: "mode", defaultValue: "closed", doc: "Either `open` or `closed`. If `open`, then the image carousel will always be shown", }, { name: "readonly", required: false, doc: "If 'readonly' or 'yes', will not show the 'link'-button", }, ] group = "images" docs = "A component showing nearby images loaded from various online services such as Mapillary. In edit mode and when used on a feature, the user can select an image to add to the feature" funcName = "nearby_images" needsUrls = CombinedFetcher.apiUrls constr( state: SpecialVisualizationState, tags: UIEventSource>, args: string[], feature: Feature, layer: LayerConfig ): SvelteUIElement { const isOpen = args[0] === "open" const readonly = args[1] === "readonly" || args[1] === "yes" const [lon, lat] = GeoOperations.centerpointCoordinates(feature) return new SvelteUIElement(isOpen ? NearbyImages : NearbyImagesCollapsed, { tags, state, lon, lat, feature, layer, linkable: !readonly, }) } } class ImageCarouselVis extends SpecialVisualizationSvelte { funcName = "image_carousel" group = "images" docs = "Creates an image carousel for the given sources. An attempt will be made to guess what source is used. Supported: Wikidata identifiers, Wikipedia pages, Wikimedia categories, IMGUR (with attribution, direct links)" args = [ { name: "image_key", type: "key", defaultValue: AllImageProviders.defaultKeys.join(";"), doc: "The keys given to the images, e.g. if image is given, the first picture URL will be added as image, the second as image:0, the third as image:1, etc... Multiple values are allowed if ';'-separated ", }, ] needsUrls = AllImageProviders.apiUrls constr(state, tags, args, feature) { let imagePrefixes: string[] = undefined if (args.length > 0) { imagePrefixes = [].concat(...args.map((a) => a.split(";"))) } const images = AllImageProviders.loadImagesFor(tags, imagePrefixes) const estimated = tags.mapD((tags) => AllImageProviders.estimateNumberOfImages(tags, imagePrefixes), ) return new SvelteUIElement(ImageCarousel, { state, tags, images, estimated, feature, }) } } class ImageUpload extends SpecialVisualizationSvelte { funcName = "image_upload" group = "images" docs = "Creates a button where a user can upload an image to panoramax" needsUrls = [Constants.panoramax.url] args = [ { type: "key", name: "image_key", doc: "Image tag to add the URL to (or image-tag:0, image-tag:1 when multiple images are added)", defaultValue: "panoramax", required: false, }, { name: "label", doc: "The text to show on the button", required: false, }, { name: "disable_blur", doc: "If set to 'true' or 'yes', then face blurring will be disabled. To be used sparingly", required: false, }, ] constr(state, tags, args, feature) { const targetKey = args[0] === "" ? undefined : args[0] const noBlur = args[3]?.toLowerCase()?.trim() return new SvelteUIElement(UploadImage, { state, tags, targetKey, feature, labelText: args[1], image: args[2], noBlur: noBlur === "true" || noBlur === "yes", }) } } export class ImageVisualisations { static initList(): SpecialVisualizationSvelte[] { return [ new NearbyImageVis(), new ImageCarouselVis(), new ImageUpload(), ] } }