Merge branch 'develop' into features/left-right-rendering

This commit is contained in:
Pieter Vander Vennet 2021-10-20 01:27:01 +02:00
commit 7b9836f273
43 changed files with 1324 additions and 1118 deletions

View file

@ -1,45 +0,0 @@
import {UIEventSource} from "../../Logic/UIEventSource";
import BaseUIElement from "../BaseUIElement";
import {VariableUiElement} from "../Base/VariableUIElement";
import Translations from "../i18n/Translations";
/**
* Shows that 'images are uploading', 'all images are uploaded' as relevant...
*/
export default class UploadFlowStateUI extends VariableUiElement {
constructor(queue: UIEventSource<string[]>, failed: UIEventSource<string[]>, success: UIEventSource<string[]>) {
const t = Translations.t.image;
super(
queue.map(queue => {
const failedReasons = failed.data
const successCount = success.data.length
const pendingCount = queue.length - successCount - failedReasons.length;
let stateMessages: BaseUIElement[] = []
if (pendingCount == 1) {
stateMessages.push(t.uploadingPicture.Clone().SetClass("alert"))
}
if (pendingCount > 1) {
stateMessages.push(t.uploadingMultiple.Subs({count: "" + pendingCount}).SetClass("alert"))
}
if (failedReasons.length > 0) {
stateMessages.push(t.uploadFailed.Clone().SetClass("alert"))
}
if (successCount > 0 && pendingCount == 0) {
stateMessages.push(t.uploadDone.SetClass("thanks"))
}
stateMessages.forEach(msg => msg.SetStyle("display: block ruby"))
return stateMessages
}, [failed, success])
);
}
}

View file

@ -23,6 +23,7 @@ import ScrollableFullScreen from "./Base/ScrollableFullScreen";
import Translations from "./i18n/Translations";
import SimpleAddUI from "./BigComponents/SimpleAddUI";
import StrayClickHandler from "../Logic/Actors/StrayClickHandler";
import Lazy from "./Base/Lazy";
export class DefaultGuiState {
public readonly welcomeMessageIsOpened;
@ -81,12 +82,22 @@ export default class DefaultGUI {
constructor(state: FeaturePipelineState, guiState: DefaultGuiState) {
this.state = state;
this._guiState = guiState;
const self = this;
if (state.layoutToUse.customCss !== undefined) {
Utils.LoadCustomCss(state.layoutToUse.customCss);
}
this.SetupUIElements();
this.SetupMap()
}
private SetupMap(){
const state = this.state;
const guiState = this._guiState;
// Attach the map
state.mainMapObject.SetClass("w-full h-full")
.AttachTo("leafletDiv")
@ -96,8 +107,28 @@ export default class DefaultGUI {
state
)
this.InitWelcomeMessage();
new ShowDataLayer({
leafletMap: state.leafletMap,
layerToShow: AllKnownLayers.sharedLayers.get("home_location"),
features: state.homeLocation,
enablePopups: false,
})
state.leafletMap.addCallbackAndRunD(_ => {
// Lets assume that all showDataLayers are initialized at this point
state.selectedElement.ping()
State.state.locationControl.ping();
return true;
})
}
private SetupUIElements(){
const state = this.state;
const guiState = this._guiState;
const self =this
Toggle.If(state.featureSwitchUserbadge,
() => new UserBadge(state)
).AttachTo("userbadge")
@ -119,36 +150,21 @@ export default class DefaultGUI {
}
new Toggle(self.InitWelcomeMessage(),
Toggle.If(state.featureSwitchIframePopoutEnabled, iframePopout),
new Toggle(new Lazy(() => self.InitWelcomeMessage()),
Toggle.If(state.featureSwitchIframePopoutEnabled, iframePopout),
state.featureSwitchWelcomeMessage
).AttachTo("messagesbox");
new LeftControls(state, guiState).AttachTo("bottom-left");
new RightControls(state).AttachTo("bottom-right");
State.state.locationControl.ping();
new CenterMessageBox(state).AttachTo("centermessage");
document
.getElementById("centermessage")
.classList.add("pointer-events-none");
new ShowDataLayer({
leafletMap: state.leafletMap,
layerToShow: AllKnownLayers.sharedLayers.get("home_location"),
features: state.homeLocation,
enablePopups: false,
})
state.leafletMap.addCallbackAndRunD(_ => {
// Lets assume that all showDataLayers are initialized at this point
state.selectedElement.ping()
return true;
})
}
private InitWelcomeMessage() {
private InitWelcomeMessage() : BaseUIElement{
const isOpened = this._guiState.welcomeMessageIsOpened
const fullOptions = new FullWelcomePaneWithTabs(isOpened, this._guiState.welcomeMessageOpenedTab, this.state);
@ -180,7 +196,7 @@ export default class DefaultGUI {
public setupClickDialogOnMap(filterViewIsOpened: UIEventSource<boolean>, state: FeaturePipelineState) {
function setup(){
function setup() {
let presetCount = 0;
for (const layer of state.layoutToUse.layers) {
for (const preset of layer.presets) {

View file

@ -9,7 +9,9 @@ import ImageProvider from "../../Logic/ImageProviders/ImageProvider";
export class ImageCarousel extends Toggle {
constructor(images: UIEventSource<{ key: string, url: string, provider: ImageProvider }[]>, tags: UIEventSource<any>) {
constructor(images: UIEventSource<{ key: string, url: string, provider: ImageProvider }[]>,
tags: UIEventSource<any>,
keys: string[]) {
const uiElements = images.map((imageURLS: { key: string, url: string, provider: ImageProvider }[]) => {
const uiElements: BaseUIElement[] = [];
for (const url of imageURLS) {

View file

@ -9,14 +9,23 @@ import LicensePicker from "../BigComponents/LicensePicker";
import Toggle from "../Input/Toggle";
import FileSelectorButton from "../Input/FileSelectorButton";
import ImgurUploader from "../../Logic/ImageProviders/ImgurUploader";
import UploadFlowStateUI from "../BigComponents/UploadFlowStateUI";
import ChangeTagAction from "../../Logic/Osm/Actions/ChangeTagAction";
import LayerConfig from "../../Models/ThemeConfig/LayerConfig";
import {FixedUiElement} from "../Base/FixedUiElement";
import {VariableUiElement} from "../Base/VariableUIElement";
export class ImageUploadFlow extends Toggle {
private static readonly uploadCountsPerId = new Map<string, UIEventSource<number>>()
constructor(tagsSource: UIEventSource<any>, imagePrefix: string = "image", text: string = undefined) {
const perId = ImageUploadFlow.uploadCountsPerId
const id = tagsSource.data.id
if(!perId.has(id)){
perId.set(id, new UIEventSource<number>(0))
}
const uploadedCount = perId.get(id)
const uploader = new ImgurUploader(url => {
// A file was uploaded - we add it to the tags of the object
@ -30,7 +39,9 @@ export class ImageUploadFlow extends Toggle {
key = imagePrefix + ":" + freeIndex;
}
console.log("Adding image:" + key, url);
Promise.resolve(State.state.changes
uploadedCount.data ++
uploadedCount.ping()
Promise.resolve(State.state.changes
.applyAction(new ChangeTagAction(
tags.id, new Tag(key, url), tagsSource.data,
{
@ -40,10 +51,6 @@ export class ImageUploadFlow extends Toggle {
)))
})
uploader.queue.addCallbackD(q => console.log("Image upload queue is ", q))
uploader.failed.addCallbackD(q => console.log("Image upload fail list is ", q))
uploader.success.addCallbackD(q => console.log("Image upload success list is ", q))
const licensePicker = new LicensePicker()
const t = Translations.t.image;
@ -105,10 +112,33 @@ export class ImageUploadFlow extends Toggle {
})
const uploadStateUi = new UploadFlowStateUI(uploader.queue, uploader.failed, uploader.success)
const uploadFlow: BaseUIElement = new Combine([
uploadStateUi,
new VariableUiElement(uploader.queue.map(q => q.length).map(l => {
if(l == 0){
return undefined;
}
if(l == 1){
return t.uploadingPicture.Clone().SetClass("alert")
}else{
return t.uploadingMultiple.Subs({count: "" + l}).SetClass("alert")
}
})),
new VariableUiElement(uploader.failed.map(q => q.length).map(l => {
if(l==0){
return undefined
}
return t.uploadFailed.Clone().SetClass("alert");
})),
new VariableUiElement(uploadedCount.map(l => {
if(l == 0){
return undefined;
}
if(l == 1){
return t.uploadDone.Clone().SetClass("thanks");
}
return t.uploadMultipleDone.Subs({count: l}).SetClass("thanks")
})),
fileSelector,
Translations.t.image.respectPrivacy.Clone().SetStyle("font-size:small;"),
licensePicker

View file

@ -83,15 +83,15 @@ export default class SpecialVisualizations {
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/prefix (multiple values allowed if comma-seperated)",
defaultValue: "image",
defaultValue: AllImageProviders.defaultKeys.join(","),
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... "
}],
constr: (state: State, tags, args) => {
let imagePrefixes = undefined;
let imagePrefixes: string[] = undefined;
if(args.length > 0){
imagePrefixes = args;
imagePrefixes = [].concat(...args.map(a => a.split(",")));
}
return new ImageCarousel(AllImageProviders.LoadImagesFor(tags, imagePrefixes), tags);
return new ImageCarousel(AllImageProviders.LoadImagesFor(tags, imagePrefixes), tags, imagePrefixes);
}
},
{