More fixes

This commit is contained in:
Pieter Vander Vennet 2021-06-16 21:23:03 +02:00
parent 2ae380f1a6
commit 9a73ae4c47
21 changed files with 203 additions and 148 deletions

View file

@ -20,6 +20,7 @@ export class SubtleButton extends UIElement {
private static generateContent(imageUrl: string | BaseUIElement, messageT: string | BaseUIElement, linkTo: { url: string | UIEventSource<string>, newTab?: boolean } = undefined): BaseUIElement {
const message = Translations.W(messageT);
message
let img;
if ((imageUrl ?? "") === "") {
img = undefined;
@ -36,7 +37,7 @@ export class SubtleButton extends UIElement {
return new Combine([
image,
message?.SetClass("blcok ml-4 overflow-ellipsis"),
]).SetClass("flex group");
]).SetClass("flex group w-full");
}
@ -44,7 +45,7 @@ export class SubtleButton extends UIElement {
new Combine([
image,
message?.SetClass("block ml-4 overflow-ellipsis")
]).SetClass("flex group"),
]).SetClass("flex group w-full"),
linkTo.url,
linkTo.newTab ?? false
)

View file

@ -23,14 +23,14 @@ export default class FullWelcomePaneWithTabs extends ScrollableFullScreen {
const layoutToUse = State.state.layoutToUse.data;
super (
() => layoutToUse.title.Clone(),
() => FullWelcomePaneWithTabs.GenerateContents(layoutToUse, State.state.osmConnection.userDetails),
() => FullWelcomePaneWithTabs.GenerateContents(layoutToUse, State.state.osmConnection.userDetails, isShown),
"welcome" ,isShown
)
}
private static ConstructBaseTabs(layoutToUse: LayoutConfig): { header: string | BaseUIElement; content: BaseUIElement }[]{
private static ConstructBaseTabs(layoutToUse: LayoutConfig, isShown: UIEventSource<boolean>): { header: string | BaseUIElement; content: BaseUIElement }[]{
let welcome: BaseUIElement = new ThemeIntroductionPanel();
let welcome: BaseUIElement = new ThemeIntroductionPanel(isShown);
if (layoutToUse.id === personal.id) {
welcome = new PersonalLayersPanel();
}
@ -58,10 +58,10 @@ export default class FullWelcomePaneWithTabs extends ScrollableFullScreen {
return tabs;
}
private static GenerateContents(layoutToUse: LayoutConfig, userDetails: UIEventSource<UserDetails>) {
private static GenerateContents(layoutToUse: LayoutConfig, userDetails: UIEventSource<UserDetails>, isShown: UIEventSource<boolean>) {
const tabs = FullWelcomePaneWithTabs.ConstructBaseTabs(layoutToUse)
const tabsWithAboutMc = [...FullWelcomePaneWithTabs.ConstructBaseTabs(layoutToUse)]
const tabs = FullWelcomePaneWithTabs.ConstructBaseTabs(layoutToUse, isShown)
const tabsWithAboutMc = [...FullWelcomePaneWithTabs.ConstructBaseTabs(layoutToUse, isShown)]
tabsWithAboutMc.push({
header: Svg.help,
content: new Combine([Translations.t.general.aboutMapcomplete.Clone(), "<br/>Version " + Constants.vNumber])

View file

@ -4,26 +4,45 @@ import LanguagePicker from "../LanguagePicker";
import Translations from "../i18n/Translations";
import {VariableUiElement} from "../Base/VariableUIElement";
import Toggle from "../Input/Toggle";
import {SubtleButton} from "../Base/SubtleButton";
import Svg from "../../Svg";
import {UIEventSource} from "../../Logic/UIEventSource";
import {FixedUiElement} from "../Base/FixedUiElement";
export default class ThemeIntroductionPanel extends VariableUiElement {
constructor() {
constructor(isShown: UIEventSource<boolean>) {
const languagePicker =
new VariableUiElement(
State.state.layoutToUse.map(layout => LanguagePicker.CreateLanguagePicker(layout.language, Translations.t.general.pickLanguage.Clone()))
)
;
const toTheMap = new SubtleButton(
new FixedUiElement(""),
Translations.t.general.openTheMap.Clone().SetClass("text-xl font-bold w-full text-center")
).onClick(() =>{
isShown.setData(false)
}).SetClass("only-on-mobile")
const plzLogIn =
Translations.t.general.loginWithOpenStreetMap
.Clone()
new SubtleButton(
Svg.osm_logo_ui(),
new Combine([Translations.t.general.loginWithOpenStreetMap
.Clone().SetClass("text-xl font-bold"),
Translations.t.general.loginOnlyNeededToEdit.Clone().SetClass("font-bold")]
).SetClass("flex flex-col text-center w-full")
)
.onClick(() => {
State.state.osmConnection.AttemptLogin()
});
const welcomeBack = Translations.t.general.welcomeBack.Clone();
const loginStatus =
new Toggle(
@ -40,6 +59,7 @@ export default class ThemeIntroductionPanel extends VariableUiElement {
super(State.state.layoutToUse.map (layout => new Combine([
layout.description.Clone(),
"<br/><br/>",
toTheMap,
loginStatus,
layout.descriptionTail.Clone(),
"<br/>",

View file

@ -13,7 +13,6 @@ export class SlideShow extends BaseUIElement {
protected InnerConstructElement(): HTMLElement {
const el = document.createElement("div")
el.classList.add("slic-carousel")
el.style.overflowX = "auto"
el.style.width = "min-content"
el.style.minWidth = "min-content"
@ -25,8 +24,9 @@ export class SlideShow extends BaseUIElement {
}
for (const element of elements ?? []) {
element.SetClass("block ml-1")
.SetStyle("width: 300px; max-height: var(--image-carousel-height); height: var(--image-carousel-height)")
element
.SetClass("block ml-1; bg-gray-200")
.SetStyle("min-width: 150; max-height: var(--image-carousel-height); min-height: var(--image-carousel-height)")
el.appendChild(element.ConstructElement())
}

View file

@ -7,77 +7,83 @@ import BaseUIElement from "../BaseUIElement";
* Supports multi-input
*/
export default class CheckBoxes extends InputElement<number[]> {
IsSelected: UIEventSource<boolean> = new UIEventSource<boolean>(false);
private readonly _element : HTMLElement
private static _nextId = 0;
private readonly value: UIEventSource<number[]>
constructor(elements: BaseUIElement[], value =new UIEventSource<number[]>([])) {
IsSelected: UIEventSource<boolean> = new UIEventSource<boolean>(false);
private readonly value: UIEventSource<number[]>
private readonly _elements: BaseUIElement[];
constructor(elements: BaseUIElement[], value = new UIEventSource<number[]>([])) {
super();
this.value = value;
elements = Utils.NoNull(elements);
const el = document.createElement("form")
for (let i = 0; i < elements.length; i++) {
let inputI = elements[i];
const input = document.createElement("input")
const id = CheckBoxes._nextId
CheckBoxes._nextId ++;
input.id = "checkbox"+id
this._elements = Utils.NoNull(elements);
this.SetClass("flex flex-col")
input.type = "checkbox"
const label = document.createElement("label")
label.htmlFor = input.id
label.appendChild(inputI.ConstructElement())
value.addCallbackAndRun(selectedValues =>{
if(selectedValues === undefined){
return;
}
if(selectedValues.indexOf(i) >= 0){
input.checked = true;
}
})
input.onchange = () => {
const index = value.data.indexOf(i);
if(input.checked && index < 0){
value.data.push(i);
value.ping();
}else if(index >= 0){
value.data.splice(index,1);
value.ping();
}
}
el.appendChild(input)
el.appendChild(document.createElement("br"))
}
}
protected InnerConstructElement(): HTMLElement {
return this._element
}
IsValid(ts: number[]): boolean {
return ts !== undefined;
}
GetValue(): UIEventSource<number[]> {
return this.value;
}
protected InnerConstructElement(): HTMLElement {
const el = document.createElement("form")
const value = this.value;
const elements = this._elements;
for (let i = 0; i < elements.length; i++) {
let inputI = elements[i];
const input = document.createElement("input")
const id = CheckBoxes._nextId
CheckBoxes._nextId++;
input.id = "checkbox" + id
input.type = "checkbox"
input.classList.add("p-1","cursor-pointer","ml-3","pl-3")
const label = document.createElement("label")
label.htmlFor = input.id
label.appendChild(inputI.ConstructElement())
label.classList.add("block","w-full","p-2","cursor-pointer","bg-red")
const wrapper = document.createElement("span")
wrapper.classList.add("flex","w-full","border", "border-gray-400")
wrapper.appendChild(input)
wrapper.appendChild(label)
el.appendChild(wrapper)
value.addCallbackAndRun(selectedValues => {
if (selectedValues === undefined) {
return;
}
if (selectedValues.indexOf(i) >= 0) {
input.checked = true;
}
})
input.onchange = () => {
// Index = index in the list of already checked items
const index = value.data.indexOf(i);
if (input.checked && index < 0) {
value.data.push(i);
value.ping();
} else if (index >= 0) {
value.data.splice(index, 1);
value.ping();
}
}
}
return el;
}
}

View file

@ -18,6 +18,7 @@ export default class DirectionInput extends InputElement<string> {
this.value = value ?? new UIEventSource<string>(undefined);
}
protected InnerConstructElement(): HTMLElement {

View file

@ -7,12 +7,19 @@ export class RadioButton<T> extends InputElement<T> {
IsSelected: UIEventSource<boolean> = new UIEventSource<boolean>(false);
private readonly value: UIEventSource<T>;
private _elements: InputElement<T>[];
private readonly _element: HTMLElement;
private _selectFirstAsDefault: boolean;
constructor(elements: InputElement<T>[],
selectFirstAsDefault = true) {
super()
elements = Utils.NoNull(elements);
this._selectFirstAsDefault = selectFirstAsDefault;
this._elements = Utils.NoNull(elements);
this.value = new UIEventSource<T>(undefined)
}
protected InnerConstructElement(): HTMLElement {
const elements = this._elements;
const selectFirstAsDefault = this._selectFirstAsDefault;
const selectedElementIndex: UIEventSource<number> = new UIEventSource<number>(null);
const value =
UIEventSource.flatten(selectedElementIndex.map(
@ -22,6 +29,7 @@ export class RadioButton<T> extends InputElement<T> {
}
}
), elements.map(e => e?.GetValue()));
value.syncWith(this.value)
if(selectFirstAsDefault){
@ -61,7 +69,20 @@ export class RadioButton<T> extends InputElement<T> {
RadioButton._nextId++
const form = document.createElement("form")
this._element = form;
const inputs = []
value.addCallbackAndRun(
selected => {
let somethingChecked = false;
for (let i = 0; i < inputs.length; i++){
let input = inputs[i];
input.checked = !somethingChecked && elements[i].IsValid(selected);
somethingChecked = somethingChecked || input.checked
}
}
)
for (let i1 = 0; i1 < elements.length; i1++) {
let element = elements[i1];
const labelHtml = element.ConstructElement();
@ -73,6 +94,7 @@ export class RadioButton<T> extends InputElement<T> {
input.id = "radio" + groupId + "-" + i1;
input.name = groupId;
input.type = "radio"
input.classList.add("p-1","cursor-pointer","ml-2","pl-2","pr-0","m-0","ml-3")
input.onchange = () => {
if(input.checked){
@ -80,30 +102,26 @@ export class RadioButton<T> extends InputElement<T> {
}
}
value.addCallbackAndRun(
selected => input.checked = element.IsValid(selected)
)
inputs.push(input)
const label = document.createElement("label")
label.appendChild(labelHtml)
label.htmlFor = input.id;
label.classList.add("block","w-full","p-2","cursor-pointer","bg-red")
const block = document.createElement("div")
block.appendChild(input)
block.appendChild(label)
block.classList.add("flex","w-full","border", "rounded-full", "border-gray-400")
form.appendChild(block)
form.addEventListener("change", () => {
// TODO FIXME
}
);
}
this.value = value;
this._elements = elements;
this.SetClass("flex flex-col")
return form;
}
IsValid(t: T): boolean {
@ -120,9 +138,6 @@ export class RadioButton<T> extends InputElement<T> {
}
protected InnerConstructElement(): HTMLElement {
return this._element;
}
/*
public ShowValue(t: T): boolean {

View file

@ -67,10 +67,10 @@ export class TextField extends InputElement<string> {
this.value.addCallbackAndRun(value => {
if (!(value !== undefined && value !== null)) {
field["value"] = "";
return;
}
// @ts-ignore
field.value = value;
field["value"] = value;
if (self.IsValid(value)) {
self.RemoveClass("invalid")
} else {

View file

@ -8,15 +8,13 @@ import State from "../../State";
import Svg from "../../Svg";
import Toggle from "../Input/Toggle";
import BaseUIElement from "../BaseUIElement";
import {FixedUiElement} from "../Base/FixedUiElement";
export default class EditableTagRendering extends Toggle {
constructor(tags: UIEventSource<any>,
configuration: TagRenderingConfig) {
const editMode = new UIEventSource<boolean>(false);
configuration: TagRenderingConfig,
editMode = new UIEventSource<boolean>(false)
) {
const answer: BaseUIElement = new TagRenderingAnswer(tags, configuration)
answer.SetClass("w-full")
let rendering = answer;

View file

@ -26,8 +26,8 @@ export class SaveButton extends Toggle {
isSaveable
)
super(
save
, pleaseLogin,
save,
pleaseLogin,
osmConnection?.userDetails?.map(userDetails => userDetails.loggedIn) ?? new UIEventSource<any>(false)
)

View file

@ -71,7 +71,8 @@ export default class TagRenderingQuestion extends UIElement {
}
this._saveButton = new SaveButton(this._inputElement.GetValue(), State.state?.osmConnection)
this._saveButton = new SaveButton(this._inputElement.GetValue(),
State.state?.osmConnection)
.onClick(save)
@ -92,7 +93,7 @@ export default class TagRenderingQuestion extends UIElement {
return tags.asHumanString(true, true, self._tags.data);
}
)
).SetClass("block")
).SetClass("block break-all")
@ -156,7 +157,9 @@ export default class TagRenderingQuestion extends UIElement {
oppositeTags.push(notSelected);
}
tags.push(TagUtils.FlattenMultiAnswer(oppositeTags));
return TagUtils.FlattenMultiAnswer(tags);
const actualTags = TagUtils.FlattenMultiAnswer(tags);
console.log("Converted ", indices.join(","), "into", actualTags.asHumanString(false, false, {}), "with elems", elements)
return actualTags;
},
(tags: TagsFilter) => {
// {key --> values[]}