Merge master

This commit is contained in:
Pieter Vander Vennet 2022-03-11 01:31:13 +01:00
commit 1455a87077
51 changed files with 62670 additions and 150 deletions

View file

@ -2,46 +2,48 @@ import {UIElement} from "../UIElement";
import BaseUIElement from "../BaseUIElement";
import {UIEventSource} from "../../Logic/UIEventSource";
import ExtraLinkConfig from "../../Models/ThemeConfig/ExtraLinkConfig";
import MapControlButton from "../MapControlButton";
import Link from "../Base/Link";
import Img from "../Base/Img";
import {SubtleButton} from "../Base/SubtleButton";
import Toggle from "../Input/Toggle";
import Loc from "../../Models/Loc";
import Locale from "../i18n/Locale";
import {Utils} from "../../Utils";
import Svg from "../../Svg";
import Translations from "../i18n/Translations";
import {Translation} from "../i18n/Translation";
export default class ExtraLinkButton extends UIElement{
export default class ExtraLinkButton extends UIElement {
private readonly _config: ExtraLinkConfig;
private readonly state: {
layoutToUse: {id: string};
featureSwitchWelcomeMessage: UIEventSource<boolean>, locationControl: UIEventSource<Loc>};
layoutToUse: { id: string, title: Translation };
featureSwitchWelcomeMessage: UIEventSource<boolean>, locationControl: UIEventSource<Loc>
};
constructor(state: {featureSwitchWelcomeMessage: UIEventSource<boolean>, locationControl: UIEventSource<Loc>, layoutToUse: {id: string}},
constructor(state: { featureSwitchWelcomeMessage: UIEventSource<boolean>, locationControl: UIEventSource<Loc>, layoutToUse: { id: string, title: Translation } },
config: ExtraLinkConfig) {
super();
this.state = state;
this._config = config;
}
protected InnerRender(): BaseUIElement {
if(this._config === undefined){
protected InnerRender(): BaseUIElement {
if (this._config === undefined) {
return undefined;
}
const c = this._config;
const isIframe = window !== window.top
if(c.requirements.has("iframe") && !isIframe){
if (c.requirements.has("iframe") && !isIframe) {
return undefined
}
if(c.requirements.has("no-iframe") && isIframe){
if (c.requirements.has("no-iframe") && isIframe) {
return undefined
}
let link : BaseUIElement
let link: BaseUIElement
const theme = this.state.layoutToUse?.id ?? ""
const href = this.state.locationControl.map(loc => {
const subs = {
@ -51,31 +53,35 @@ export default class ExtraLinkButton extends UIElement{
}
return Utils.SubstituteKeys(c.href, subs)
})
if(c.text === undefined){
link = new MapControlButton(
new Link(new Img(c.icon), href, c.newTab).SetClass("block w-full h-full p-1.5")
)
}else {
let img : BaseUIElement = undefined
if(c.icon !== undefined){
img = new Img(c.icon).SetClass("h-6")
}
link = new SubtleButton(img,c.text, {url:
href,
newTab: c.newTab})
let img: BaseUIElement = Svg.pop_out_ui()
if (c.icon !== undefined) {
img = new Img(c.icon).SetClass("h-6")
}
if(c.requirements.has("no-welcome-message")){
let text: Translation
if (c.text === undefined) {
text = Translations.t.general.screenToSmall.Fuse(this.state.layoutToUse.title, "{theme}")
} else {
text = c.text.Clone()
}
link = new SubtleButton(img, text, {
url:
href,
newTab: c.newTab
})
if (c.requirements.has("no-welcome-message")) {
link = new Toggle(undefined, link, this.state.featureSwitchWelcomeMessage)
}
if(c.requirements.has("welcome-message")){
link = new Toggle(link, undefined, this.state.featureSwitchWelcomeMessage)
if (c.requirements.has("welcome-message")) {
link = new Toggle(link, undefined, this.state.featureSwitchWelcomeMessage)
}
return link;
}
}

View file

@ -168,6 +168,11 @@ export default class DefaultGUI {
]).SetClass("flex flex-col")
.AttachTo("userbadge")
new Combine([
new ExtraLinkButton(state, {...state.layoutToUse.extraLink, newTab: true, requirements: new Set<"iframe" | "no-iframe" | "welcome-message" | "no-welcome-message">( ) })
]).SetClass("flex items-center justify-center normal-background h-full")
.AttachTo("on-small-screen")
Toggle.If(state.featureSwitchSearch,
() => new SearchAndGo(state))
.AttachTo("searchbox");

View file

@ -191,7 +191,7 @@ ${Utils.special_visualizations_importRequirementDocs}
importFlow,
isImported
),
t.zoomInMore,
t.zoomInMore.SetClass("alert"),
state.locationControl.map(l => l.zoom >= 18)
),
pleaseLoginButton,

View file

@ -71,7 +71,7 @@ export default class NewNoteUi extends Toggle {
new Combine([new Toggle(undefined, t.warnAnonymous.SetClass("alert"), state?.osmConnection?.isLoggedIn),
new Toggle(postNote,
t.textNeeded.SetClass("alert"),
text.GetValue().map(txt => txt.length > 3)
text.GetValue().map(txt => txt?.length > 3)
)
]).SetClass("flex justify-end items-center")

View file

@ -46,6 +46,7 @@ import FileSelectorButton from "./Input/FileSelectorButton";
import {LoginToggle} from "./Popup/LoginButton";
import {start} from "repl";
import {SubstitutedTranslation} from "./SubstitutedTranslation";
import {Feature} from "@turf/turf";
export interface SpecialVisualization {
funcName: string,
@ -95,6 +96,88 @@ export class AllTagsPanel extends VariableUiElement {
}
}
class CloseNoteButton implements SpecialVisualization {
public readonly funcName = "close_note"
public readonly docs = "Button to close a note. A predifined text can be defined to close the note with. If the note is already closed, will show a small text."
public readonly args = [
{
name: "text",
doc: "Text to show on this button",
},
{
name: "icon",
doc: "Icon to show",
defaultValue: "checkmark.svg"
},
{
name: "idkey",
doc: "The property name where the ID of the note to close can be found",
defaultValue: "id"
},
{
name: "comment",
doc: "Text to add onto the note when closing",
},
{
name: "minZoom",
doc: "If set, only show the closenote button if zoomed in enough"
},
{
name: "zoomButton",
doc: "Text to show if not zoomed in enough"
}
]
public constr(state: FeaturePipelineState, tags, args): BaseUIElement {
const t = Translations.t.notes;
const params: {
text: string,
icon: string,
idkey: string,
comment: string,
minZoom: string,
zoomButton: string
} = Utils.ParseVisArgs(this.args, args)
let icon = Svg.checkmark_svg()
if (params.icon !== "checkmark.svg" && (args[2] ?? "") !== "") {
icon = new Img(args[1])
}
let textToShow = t.closeNote;
if ((params.text ?? "") !== "") {
textToShow = Translations.T(args[0])
}
let closeButton: BaseUIElement = new SubtleButton(icon, textToShow)
const isClosed = tags.map(tags => (tags["closed_at"] ?? "") !== "");
closeButton.onClick(() => {
const id = tags.data[args[2] ?? "id"]
state.osmConnection.closeNote(id, args[3])
?.then(_ => {
tags.data["closed_at"] = new Date().toISOString();
tags.ping()
})
})
if((params.minZoom??"") !== "" && !isNaN(Number(params.minZoom))){
closeButton = new Toggle(
closeButton,
params.zoomButton ?? "",
state. locationControl.map(l => l.zoom >= Number(params.minZoom))
)
}
return new LoginToggle(new Toggle(
t.isClosed.SetClass("thanks"),
closeButton,
isClosed
), t.loginToClose, state)
}
}
export default class SpecialVisualizations {
public static specialVisualizations = SpecialVisualizations.init()
@ -655,58 +738,7 @@ export default class SpecialVisualizations {
})
}
},
{
funcName: "close_note",
docs: "Button to close a note. A predifined text can be defined to close the note with. If the note is already closed, will show a small text.",
args: [
{
name: "text",
doc: "Text to show on this button",
},
{
name: "icon",
doc: "Icon to show",
defaultValue: "checkmark.svg"
},
{
name: "Id-key",
doc: "The property name where the ID of the note to close can be found",
defaultValue: "id"
},
{
name: "comment",
doc: "Text to add onto the note when closing",
}
],
constr: (state, tags, args) => {
const t = Translations.t.notes;
let icon = Svg.checkmark_svg()
if (args[1] !== "checkmark.svg" && (args[2] ?? "") !== "") {
icon = new Img(args[1])
}
let textToShow = t.closeNote;
if ((args[0] ?? "") !== "") {
textToShow = Translations.T(args[0])
}
const closeButton = new SubtleButton(icon, textToShow)
const isClosed = tags.map(tags => (tags["closed_at"] ?? "") !== "");
closeButton.onClick(() => {
const id = tags.data[args[2] ?? "id"]
state.osmConnection.closeNote(id, args[3])
?.then(_ => {
tags.data["closed_at"] = new Date().toISOString();
tags.ping()
})
})
return new LoginToggle(new Toggle(
t.isClosed.SetClass("thanks"),
closeButton,
isClosed
), t.loginToClose, state)
}
},
new CloseNoteButton(),
{
funcName: "add_note_comment",
docs: "A textfield to add a comment to a node (with the option to close the note).",
@ -778,7 +810,7 @@ export default class SpecialVisualizations {
new Title("Add a comment"),
textField,
new Combine([
new Toggle(addCommentButton, undefined, textField.GetValue().map(t => t !==undefined && t.length > 1)).SetClass("mr-2")
new Toggle(addCommentButton, undefined, textField.GetValue().map(t => t !== undefined && t.length > 1)).SetClass("mr-2")
, stateButtons]).SetClass("flex justify-end")
]).SetClass("border-2 border-black rounded-xl p-4 block"),
t.loginToAddComment, state)
@ -860,15 +892,15 @@ export default class SpecialVisualizations {
},
{
funcName:"title",
funcName: "title",
args: [],
docs:"Shows the title of the popup. Useful for some cases, e.g. 'What is phone number of {title()}?'",
example:"`What is the phone number of {title()}`, which might automatically become `What is the phone number of XYZ`.",
docs: "Shows the title of the popup. Useful for some cases, e.g. 'What is phone number of {title()}?'",
example: "`What is the phone number of {title()}`, which might automatically become `What is the phone number of XYZ`.",
constr: (state, tagsSource, args, guistate) =>
new VariableUiElement(tagsSource.map(tags => {
const layer = state.layoutToUse.getMatchingLayer(tags)
const title = layer?.title?.GetRenderValue(tags)
if(title === undefined){
if (title === undefined) {
return undefined
}
return new SubstitutedTranslation(title, tagsSource, state)