forked from MapComplete/MapComplete
Styling tweak
Add mapillary link to nearby_images Fix licenses Add missing assets First version of nearby-images
This commit is contained in:
parent
a4f2fa63a5
commit
7559f9259b
52 changed files with 674 additions and 207 deletions
133
UI/Popup/NearbyImages.ts
Normal file
133
UI/Popup/NearbyImages.ts
Normal file
|
@ -0,0 +1,133 @@
|
|||
import Combine from "../Base/Combine";
|
||||
import {UIEventSource} from "../../Logic/UIEventSource";
|
||||
import {SlideShow} from "../Image/SlideShow";
|
||||
import Toggle from "../Input/Toggle";
|
||||
import Loading from "../Base/Loading";
|
||||
import {AttributedImage} from "../Image/AttributedImage";
|
||||
import AllImageProviders from "../../Logic/ImageProviders/AllImageProviders";
|
||||
import Svg from "../../Svg";
|
||||
import BaseUIElement from "../BaseUIElement";
|
||||
import {InputElement} from "../Input/InputElement";
|
||||
import {VariableUiElement} from "../Base/VariableUIElement";
|
||||
import Translations from "../i18n/Translations";
|
||||
import {Mapillary} from "../../Logic/ImageProviders/Mapillary";
|
||||
|
||||
export interface P4CPicture {
|
||||
pictureUrl: string,
|
||||
date: number,
|
||||
coordinates: { lat: number, lng: number },
|
||||
provider: "Mapillary" | string,
|
||||
author,
|
||||
license,
|
||||
detailsUrl: string,
|
||||
direction,
|
||||
osmTags: object /*To copy straight into OSM!*/
|
||||
,
|
||||
thumbUrl: string,
|
||||
details: {
|
||||
isSpherical: boolean,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
interface NearbyImageOptions {
|
||||
lon: number,
|
||||
lat: number,
|
||||
radius: number,
|
||||
maxDaysOld?: 1095,
|
||||
blacklist: UIEventSource<{url: string}[]>
|
||||
}
|
||||
|
||||
export default class NearbyImages extends VariableUiElement {
|
||||
|
||||
constructor(options: NearbyImageOptions) {
|
||||
const t = Translations.t.image.nearbyPictures
|
||||
const P4C = require("../../vendor/P4C.min")
|
||||
const picManager = new P4C.PicturesManager({});
|
||||
|
||||
const loadedPictures = UIEventSource.FromPromise<P4CPicture[]>(
|
||||
picManager.startPicsRetrievalAround(new P4C.LatLng(options.lat, options.lon), options.radius, {
|
||||
mindate: new Date().getTime() - (options.maxDaysOld ?? 1095) * 24 * 60 * 60 * 1000
|
||||
})
|
||||
).map(images => {
|
||||
console.log("Images are" ,images, "blacklisted is", options.blacklist.data)
|
||||
images?.sort((a, b) => b.date - a.date)
|
||||
return images ?.filter(i => !(options.blacklist?.data?.some(blacklisted =>
|
||||
Mapillary.sameUrl(i.pictureUrl, blacklisted.url)))
|
||||
&& i.details.isSpherical === false);
|
||||
}, [options.blacklist])
|
||||
|
||||
super(loadedPictures.map(images => {
|
||||
if(images === undefined){
|
||||
return new Loading(t.loading);
|
||||
}
|
||||
if(images.length === 0){
|
||||
return t.nothingFound.SetClass("alert block")
|
||||
}
|
||||
return new SlideShow(loadedPictures.map(imgs => (imgs ?? []).slice(0, 25).map(i => this.prepareElement(i))))
|
||||
}));
|
||||
|
||||
}
|
||||
|
||||
protected prepareElement(info: P4CPicture): BaseUIElement {
|
||||
const provider = AllImageProviders.byName(info.provider);
|
||||
return new AttributedImage({url: info.pictureUrl, provider})
|
||||
}
|
||||
|
||||
private asAttributedImage(info: P4CPicture): AttributedImage {
|
||||
const provider = AllImageProviders.byName(info.provider);
|
||||
return new AttributedImage({url: info.thumbUrl, provider, date: new Date(info.date)})
|
||||
}
|
||||
|
||||
protected asToggle(info:P4CPicture): Toggle {
|
||||
const imgNonSelected = this.asAttributedImage(info);
|
||||
const imageSelected = this.asAttributedImage(info);
|
||||
|
||||
const nonSelected = new Combine([imgNonSelected]).SetClass("relative block")
|
||||
const hoveringCheckmark =
|
||||
new Combine([Svg.confirm_svg().SetClass("block w-24 h-24 -ml-12 -mt-12")]).SetClass("absolute left-1/2 top-1/2 w-0")
|
||||
const selected = new Combine([
|
||||
imageSelected,
|
||||
hoveringCheckmark,
|
||||
]).SetClass("relative block")
|
||||
|
||||
return new Toggle(selected, nonSelected).SetClass("").ToggleOnClick();
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export class SelectOneNearbyImage extends NearbyImages implements InputElement<P4CPicture> {
|
||||
private readonly value: UIEventSource<P4CPicture>;
|
||||
|
||||
constructor(options: NearbyImageOptions & {value?: UIEventSource<P4CPicture>}) {
|
||||
super(options)
|
||||
this.value = options.value ?? new UIEventSource<P4CPicture>(undefined);
|
||||
}
|
||||
|
||||
GetValue(): UIEventSource<P4CPicture> {
|
||||
return this.value;
|
||||
}
|
||||
|
||||
IsValid(t: P4CPicture): boolean {
|
||||
return false;
|
||||
}
|
||||
|
||||
protected prepareElement(info: P4CPicture): BaseUIElement {
|
||||
const toggle = super.asToggle(info)
|
||||
toggle.isEnabled.addCallback(enabled => {
|
||||
if (enabled) {
|
||||
this.value.setData(info)
|
||||
}
|
||||
})
|
||||
|
||||
this.value.addCallback(inf => {
|
||||
if(inf !== info){
|
||||
toggle.isEnabled.setData(false)
|
||||
}
|
||||
})
|
||||
|
||||
return toggle
|
||||
}
|
||||
|
||||
}
|
|
@ -2,10 +2,11 @@ import {UIEventSource} from "../../Logic/UIEventSource";
|
|||
import Translations from "../i18n/Translations";
|
||||
import {OsmConnection} from "../../Logic/Osm/OsmConnection";
|
||||
import Toggle from "../Input/Toggle";
|
||||
import BaseUIElement from "../BaseUIElement";
|
||||
|
||||
export class SaveButton extends Toggle {
|
||||
|
||||
constructor(value: UIEventSource<any>, osmConnection: OsmConnection) {
|
||||
constructor(value: UIEventSource<any>, osmConnection: OsmConnection, textEnabled ?: BaseUIElement, textDisabled ?: BaseUIElement) {
|
||||
if (value === undefined) {
|
||||
throw "No event source for savebutton, something is wrong"
|
||||
}
|
||||
|
@ -17,9 +18,9 @@ export class SaveButton extends Toggle {
|
|||
|
||||
const isSaveable = value.map(v => v !== false && (v ?? "") !== "")
|
||||
|
||||
const text = Translations.t.general.save
|
||||
const saveEnabled = text.Clone().SetClass(`btn`);
|
||||
const saveDisabled = text.Clone().SetClass(`btn btn-disabled`);
|
||||
const saveEnabled = (textEnabled ?? Translations.t.general.save.Clone()).SetClass(`btn`);
|
||||
const saveDisabled = (textDisabled ?? Translations.t.general.save.Clone()).SetClass(`btn btn-disabled`);
|
||||
|
||||
const save = new Toggle(
|
||||
saveEnabled,
|
||||
saveDisabled,
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue