forked from MapComplete/MapComplete
Refactoring: attempting to make State smaller
This commit is contained in:
parent
a6f56acad6
commit
849c61c8a1
28 changed files with 529 additions and 485 deletions
|
@ -1,117 +0,0 @@
|
|||
import {InputElement} from "../InputElement";
|
||||
import {UIEventSource} from "../../../Logic/UIEventSource";
|
||||
import {UIElement} from "../../UIElement";
|
||||
import Combine from "../../Base/Combine";
|
||||
import {OH} from "../../../Logic/OpeningHours";
|
||||
import OpeningHoursPicker from "./OpeningHoursPicker";
|
||||
import {VariableUiElement} from "../../Base/VariableUIElement";
|
||||
import Translations from "../../i18n/Translations";
|
||||
import {FixedUiElement} from "../../Base/FixedUiElement";
|
||||
import PublicHolidayInput from "./PublicHolidayInput";
|
||||
|
||||
|
||||
/**
|
||||
* The full opening hours element, including the table, opening hours picker.
|
||||
* Keeps track of unparsed rules
|
||||
* Exports everything conventiently as a string, for direct use
|
||||
*/
|
||||
export default class OpeningHoursInput extends InputElement<string> {
|
||||
|
||||
|
||||
private readonly _value: UIEventSource<string>;
|
||||
|
||||
private readonly _ohPicker: UIElement;
|
||||
private readonly _leftoverWarning: UIElement;
|
||||
private readonly _phSelector: UIElement;
|
||||
|
||||
constructor(value: UIEventSource<string> = new UIEventSource<string>("")) {
|
||||
super();
|
||||
|
||||
|
||||
const leftoverRules = value.map<string[]>(str => {
|
||||
if (str === undefined) {
|
||||
return []
|
||||
}
|
||||
const leftOvers: string[] = [];
|
||||
const rules = str.split(";");
|
||||
for (const rule of rules) {
|
||||
if (OH.ParseRule(rule) !== null) {
|
||||
continue;
|
||||
}
|
||||
if (PublicHolidayInput.LoadValue(rule) !== null) {
|
||||
continue;
|
||||
}
|
||||
leftOvers.push(rule);
|
||||
}
|
||||
return leftOvers;
|
||||
})
|
||||
// NOte: MUST be bound AFTER the leftover rules!
|
||||
const rulesFromOhPicker = value.map(OH.Parse);
|
||||
|
||||
const ph = value.map<string>(str => {
|
||||
if (str === undefined) {
|
||||
return ""
|
||||
}
|
||||
const rules = str.split(";");
|
||||
for (const rule of rules) {
|
||||
if (PublicHolidayInput.LoadValue(rule) !== null) {
|
||||
return rule;
|
||||
}
|
||||
}
|
||||
return "";
|
||||
})
|
||||
this._phSelector = new PublicHolidayInput(ph);
|
||||
|
||||
function update() {
|
||||
let rules = OH.ToString(rulesFromOhPicker.data);
|
||||
if (leftoverRules.data.length != 0) {
|
||||
rules += ";" + leftoverRules.data.join(";")
|
||||
}
|
||||
const phData = ph.data;
|
||||
if (phData !== undefined && phData !== "") {
|
||||
rules += ";" + phData;
|
||||
}
|
||||
value.setData(rules);
|
||||
}
|
||||
|
||||
rulesFromOhPicker.addCallback(update);
|
||||
ph.addCallback(update);
|
||||
|
||||
this._leftoverWarning = new VariableUiElement(leftoverRules.map((leftovers: string[]) => {
|
||||
|
||||
if (leftovers.length == 0) {
|
||||
return "";
|
||||
}
|
||||
return new Combine([
|
||||
Translations.t.general.opening_hours.not_all_rules_parsed,
|
||||
new FixedUiElement(leftovers.map(r => `${r}<br/>`).join("")).SetClass("subtle")
|
||||
]).Render();
|
||||
|
||||
}))
|
||||
|
||||
this._ohPicker = new OpeningHoursPicker(rulesFromOhPicker);
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
GetValue(): UIEventSource<string> {
|
||||
return this._value;
|
||||
}
|
||||
|
||||
InnerRender(): string {
|
||||
return new Combine([
|
||||
this._leftoverWarning,
|
||||
this._ohPicker,
|
||||
this._phSelector
|
||||
]).Render();
|
||||
}
|
||||
|
||||
|
||||
public readonly IsSelected: UIEventSource<boolean> = new UIEventSource<boolean>(false);
|
||||
|
||||
IsValid(t: string): boolean {
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
|
@ -1,65 +0,0 @@
|
|||
import {UIElement} from "../../UIElement";
|
||||
import {InputElement} from "../InputElement";
|
||||
import {OpeningHour, OH} from "../../../Logic/OpeningHours";
|
||||
import {UIEventSource} from "../../../Logic/UIEventSource";
|
||||
import OpeningHoursPickerTable from "./OpeningHoursPickerTable";
|
||||
import OpeningHoursRange from "./OpeningHoursRange";
|
||||
import Combine from "../../Base/Combine";
|
||||
|
||||
export default class OpeningHoursPicker extends InputElement<OpeningHour[]> {
|
||||
private readonly _ohs: UIEventSource<OpeningHour[]>;
|
||||
public readonly IsSelected: UIEventSource<boolean> = new UIEventSource<boolean>(false);
|
||||
|
||||
private readonly _backgroundTable: OpeningHoursPickerTable;
|
||||
|
||||
private readonly _weekdays: UIEventSource<UIElement[]> = new UIEventSource<UIElement[]>([]);
|
||||
|
||||
constructor(ohs: UIEventSource<OpeningHour[]> = new UIEventSource<OpeningHour[]>([])) {
|
||||
super();
|
||||
this._ohs = ohs;
|
||||
this._backgroundTable = new OpeningHoursPickerTable(this._weekdays, this._ohs);
|
||||
const self = this;
|
||||
|
||||
|
||||
this._ohs.addCallback(ohs => {
|
||||
self._ohs.setData(OH.MergeTimes(ohs));
|
||||
})
|
||||
|
||||
ohs.addCallbackAndRun(ohs => {
|
||||
const perWeekday: UIElement[][] = [];
|
||||
for (let i = 0; i < 7; i++) {
|
||||
perWeekday[i] = [];
|
||||
}
|
||||
|
||||
for (const oh of ohs) {
|
||||
const source = new UIEventSource<OpeningHour>(oh)
|
||||
source.addCallback(_ => {
|
||||
self._ohs.setData(OH.MergeTimes(self._ohs.data))
|
||||
})
|
||||
const r = new OpeningHoursRange(source, `oh-table-${this._backgroundTable.id}`);
|
||||
perWeekday[oh.weekday].push(r);
|
||||
}
|
||||
|
||||
for (let i = 0; i < 7; i++) {
|
||||
self._weekdays.data[i] = new Combine(perWeekday[i]);
|
||||
}
|
||||
self._weekdays.ping();
|
||||
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
InnerRender(): string {
|
||||
return this._backgroundTable.Render();
|
||||
}
|
||||
|
||||
GetValue(): UIEventSource<OpeningHour[]> {
|
||||
return this._ohs
|
||||
}
|
||||
|
||||
|
||||
IsValid(t: OpeningHour[]): boolean {
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
|
@ -1,294 +0,0 @@
|
|||
import {InputElement} from "../InputElement";
|
||||
import {OpeningHour} from "../../../Logic/OpeningHours";
|
||||
import {UIEventSource} from "../../../Logic/UIEventSource";
|
||||
import {Utils} from "../../../Utils";
|
||||
import {UIElement} from "../../UIElement";
|
||||
import Translations from "../../i18n/Translations";
|
||||
import {Browser} from "leaflet";
|
||||
|
||||
/**
|
||||
* This is the base-table which is selectable by hovering over it.
|
||||
* It will genarate the currently selected opening hour.
|
||||
*/
|
||||
export default class OpeningHoursPickerTable extends InputElement<OpeningHour[]> {
|
||||
public readonly IsSelected: UIEventSource<boolean>;
|
||||
private readonly weekdays: UIEventSource<UIElement[]>;
|
||||
|
||||
public static readonly days: UIElement[] =
|
||||
[
|
||||
Translations.t.general.weekdays.abbreviations.monday,
|
||||
Translations.t.general.weekdays.abbreviations.tuesday,
|
||||
Translations.t.general.weekdays.abbreviations.wednesday,
|
||||
Translations.t.general.weekdays.abbreviations.thursday,
|
||||
Translations.t.general.weekdays.abbreviations.friday,
|
||||
Translations.t.general.weekdays.abbreviations.saturday,
|
||||
Translations.t.general.weekdays.abbreviations.sunday
|
||||
]
|
||||
|
||||
|
||||
private readonly source: UIEventSource<OpeningHour[]>;
|
||||
|
||||
|
||||
constructor(weekdays: UIEventSource<UIElement[]>, source?: UIEventSource<OpeningHour[]>) {
|
||||
super(weekdays);
|
||||
this.weekdays = weekdays;
|
||||
this.source = source ?? new UIEventSource<OpeningHour[]>([]);
|
||||
this.IsSelected = new UIEventSource<boolean>(false);
|
||||
this.SetStyle("width:100%;height:100%;display:block;");
|
||||
|
||||
}
|
||||
|
||||
InnerRender(): string {
|
||||
let rows = "";
|
||||
const self = this;
|
||||
for (let h = 0; h < 24; h++) {
|
||||
let hs = "" + h;
|
||||
if (hs.length == 1) {
|
||||
hs = "0" + hs;
|
||||
}
|
||||
|
||||
|
||||
rows += `<tr><td rowspan="2" class="oh-left-col oh-timecell-full">${hs}:00</td>` +
|
||||
Utils.Times(weekday => `<td id="${this.id}-timecell-${weekday}-${h}" class="oh-timecell oh-timecell-full oh-timecell-${weekday}"></td>`, 7) +
|
||||
'</tr><tr>' +
|
||||
Utils.Times(id => `<td id="${this.id}-timecell-${id}-${h}-30" class="oh-timecell oh-timecell-half oh-timecell-${id}"></td>`, 7) +
|
||||
'</tr>';
|
||||
}
|
||||
let days = OpeningHoursPickerTable.days.map((day, i) => {
|
||||
const innerContent = self.weekdays.data[i]?.Render() ?? "";
|
||||
return day.Render() + "<span style='width:100%; display:block; position: relative;'>"+innerContent+"</span>";
|
||||
}).join("</th><th width='14%'>");
|
||||
return `<table id="oh-table-${this.id}" class="oh-table"><tr><th></th><th width='14%'>${days}</th></tr>${rows}</table>`;
|
||||
}
|
||||
|
||||
protected InnerUpdate() {
|
||||
const self = this;
|
||||
const table = (document.getElementById(`oh-table-${this.id}`) as HTMLTableElement);
|
||||
console.log("Inner update!")
|
||||
if (table === undefined || table === null) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (const uielement of this.weekdays.data) {
|
||||
uielement.Update();
|
||||
}
|
||||
|
||||
let mouseIsDown = false;
|
||||
let selectionStart: [number, number] = undefined;
|
||||
let selectionEnd: [number, number] = undefined;
|
||||
|
||||
function h(timeSegment: number) {
|
||||
return Math.floor(timeSegment / 2);
|
||||
}
|
||||
|
||||
function m(timeSegment: number) {
|
||||
return (timeSegment % 2) * 30;
|
||||
}
|
||||
|
||||
function startSelection(i: number, j: number) {
|
||||
mouseIsDown = true;
|
||||
selectionStart = [i, j];
|
||||
selectionEnd = [i, j];
|
||||
}
|
||||
|
||||
function endSelection() {
|
||||
if (selectionStart === undefined) {
|
||||
return;
|
||||
}
|
||||
if (!mouseIsDown) {
|
||||
return;
|
||||
}
|
||||
mouseIsDown = false
|
||||
const dStart = Math.min(selectionStart[1], selectionEnd[1]);
|
||||
const dEnd = Math.max(selectionStart[1], selectionEnd[1]);
|
||||
const timeStart = Math.min(selectionStart[0], selectionEnd[0]) - 1;
|
||||
const timeEnd = Math.max(selectionStart[0], selectionEnd[0]) - 1;
|
||||
for (let weekday = dStart; weekday <= dEnd; weekday++) {
|
||||
const oh: OpeningHour = {
|
||||
weekday: weekday,
|
||||
startHour: h(timeStart),
|
||||
startMinutes: m(timeStart),
|
||||
endHour: h(timeEnd + 1),
|
||||
endMinutes: m(timeEnd + 1)
|
||||
}
|
||||
if (oh.endHour > 23) {
|
||||
oh.endHour = 24;
|
||||
oh.endMinutes = 0;
|
||||
}
|
||||
self.source.data.push(oh);
|
||||
}
|
||||
self.source.ping();
|
||||
|
||||
// Clear the highlighting
|
||||
let header = table.rows[0];
|
||||
for (let j = 1; j < header.cells.length; j++) {
|
||||
header.cells[j].classList?.remove("oh-timecol-selected")
|
||||
}
|
||||
for (let i = 1; i < table.rows.length; i++) {
|
||||
let row = table.rows[i]
|
||||
for (let j = 0; j < row.cells.length; j++) {
|
||||
let cell = row.cells[j]
|
||||
cell?.classList?.remove("oh-timecell-selected");
|
||||
row.classList?.remove("oh-timerow-selected");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
table.onmouseup = () => {
|
||||
endSelection();
|
||||
};
|
||||
table.onmouseleave = () => {
|
||||
endSelection();
|
||||
};
|
||||
|
||||
let lastSelectionIend, lastSelectionJEnd;
|
||||
function selectAllBetween(iEnd, jEnd) {
|
||||
|
||||
if (lastSelectionIend === iEnd && lastSelectionJEnd === jEnd) {
|
||||
return; // We already did this
|
||||
}
|
||||
lastSelectionIend = iEnd;
|
||||
lastSelectionJEnd = jEnd;
|
||||
|
||||
let iStart = selectionStart[0];
|
||||
let jStart = selectionStart[1];
|
||||
|
||||
if (iStart > iEnd) {
|
||||
const h = iStart;
|
||||
iStart = iEnd;
|
||||
iEnd = h;
|
||||
}
|
||||
if (jStart > jEnd) {
|
||||
const h = jStart;
|
||||
jStart = jEnd;
|
||||
jEnd = h;
|
||||
}
|
||||
|
||||
let header = table.rows[0];
|
||||
for (let j = 1; j < header.cells.length; j++) {
|
||||
let cell = header.cells[j]
|
||||
cell.classList?.remove("oh-timecol-selected-round-left");
|
||||
cell.classList?.remove("oh-timecol-selected-round-right");
|
||||
|
||||
if (jStart + 1 <= j && j <= jEnd + 1) {
|
||||
cell.classList?.add("oh-timecol-selected")
|
||||
if (jStart + 1 == j) {
|
||||
cell.classList?.add("oh-timecol-selected-round-left");
|
||||
}
|
||||
if (jEnd + 1 == j) {
|
||||
cell.classList?.add("oh-timecol-selected-round-right");
|
||||
}
|
||||
|
||||
} else {
|
||||
cell.classList?.remove("oh-timecol-selected")
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
for (let i = 1; i < table.rows.length; i++) {
|
||||
let row = table.rows[i];
|
||||
if (iStart <= i && i <= iEnd) {
|
||||
row.classList?.add("oh-timerow-selected")
|
||||
} else {
|
||||
row.classList?.remove("oh-timerow-selected")
|
||||
}
|
||||
for (let j = 0; j < row.cells.length; j++) {
|
||||
let cell = row.cells[j]
|
||||
if (cell === undefined) {
|
||||
continue;
|
||||
}
|
||||
let offset = 0;
|
||||
if (i % 2 == 1) {
|
||||
if (j == 0) {
|
||||
// This is the first column of a full hour -> This is the time indication (skip)
|
||||
continue;
|
||||
}
|
||||
offset = -1;
|
||||
}
|
||||
|
||||
|
||||
if (iStart <= i && i <= iEnd &&
|
||||
jStart <= j + offset && j + offset <= jEnd) {
|
||||
cell?.classList?.add("oh-timecell-selected")
|
||||
} else {
|
||||
cell?.classList?.remove("oh-timecell-selected")
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
for (let i = 1; i < table.rows.length; i++) {
|
||||
let row = table.rows[i]
|
||||
for (let j = 0; j < row.cells.length; j++) {
|
||||
let cell = row.cells[j]
|
||||
let offset = 0;
|
||||
if (i % 2 == 1) {
|
||||
if (j == 0) {
|
||||
continue;
|
||||
}
|
||||
offset = -1;
|
||||
}
|
||||
|
||||
|
||||
cell.onmousedown = (ev) => {
|
||||
ev.preventDefault();
|
||||
startSelection(i, j + offset)
|
||||
selectAllBetween(i, j + offset);
|
||||
}
|
||||
cell.ontouchstart = (ev) => {
|
||||
ev.preventDefault();
|
||||
startSelection(i, j + offset);
|
||||
selectAllBetween(i, j + offset);
|
||||
}
|
||||
cell.onmouseenter = () => {
|
||||
if (mouseIsDown) {
|
||||
selectionEnd = [i, j + offset];
|
||||
selectAllBetween(i, j + offset)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
cell.ontouchmove = (ev: TouchEvent) => {
|
||||
|
||||
ev.preventDefault();
|
||||
for (const k in ev.targetTouches) {
|
||||
const touch = ev.targetTouches[k];
|
||||
if(touch.clientX === undefined || touch.clientY === undefined){
|
||||
continue;
|
||||
}
|
||||
const elUnderTouch = document.elementFromPoint(
|
||||
touch.clientX,
|
||||
touch.clientY
|
||||
);
|
||||
// @ts-ignore
|
||||
const f = elUnderTouch.onmouseenter;
|
||||
if (f) {
|
||||
f();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
cell.ontouchend = (ev) => {
|
||||
ev.preventDefault();
|
||||
endSelection();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
IsValid(t: OpeningHour[]): boolean {
|
||||
return true;
|
||||
}
|
||||
|
||||
GetValue(): UIEventSource<OpeningHour[]> {
|
||||
return this.source;
|
||||
}
|
||||
|
||||
}
|
|
@ -1,104 +0,0 @@
|
|||
import {UIElement} from "../../UIElement";
|
||||
import {UIEventSource} from "../../../Logic/UIEventSource";
|
||||
import {OH, OpeningHour} from "../../../Logic/OpeningHours";
|
||||
import Combine from "../../Base/Combine";
|
||||
import {Utils} from "../../../Utils";
|
||||
import {FixedUiElement} from "../../Base/FixedUiElement";
|
||||
import {VariableUiElement} from "../../Base/VariableUIElement";
|
||||
import Svg from "../../../Svg";
|
||||
|
||||
/**
|
||||
* A single opening hours range, shown on top of the OH-picker table
|
||||
*/
|
||||
export default class OpeningHoursRange extends UIElement {
|
||||
private _oh: UIEventSource<OpeningHour>;
|
||||
|
||||
private readonly _startTime: UIElement;
|
||||
private readonly _endTime: UIElement;
|
||||
private readonly _deleteRange: UIElement;
|
||||
private readonly _tableId: string;
|
||||
|
||||
constructor(oh: UIEventSource<OpeningHour>, tableId: string) {
|
||||
super(oh);
|
||||
this._tableId = tableId;
|
||||
const self = this;
|
||||
this._oh = oh;
|
||||
this.SetClass("oh-timerange");
|
||||
oh.addCallbackAndRun(() => {
|
||||
const el = document.getElementById(this.id) as HTMLElement;
|
||||
self.InnerUpdate(el);
|
||||
})
|
||||
|
||||
this._deleteRange =
|
||||
Svg.delete_icon_ui()
|
||||
.SetClass("oh-delete-range")
|
||||
.onClick(() => {
|
||||
oh.data.weekday = undefined;
|
||||
oh.ping();
|
||||
});
|
||||
|
||||
|
||||
this._startTime = new VariableUiElement(oh.map(oh => {
|
||||
return Utils.TwoDigits(oh.startHour) + ":" + Utils.TwoDigits(oh.startMinutes);
|
||||
})).SetClass("oh-timerange-label")
|
||||
|
||||
this._endTime = new VariableUiElement(oh.map(oh => {
|
||||
return Utils.TwoDigits(oh.endHour) + ":" + Utils.TwoDigits(oh.endMinutes);
|
||||
})).SetClass("oh-timerange-label")
|
||||
|
||||
|
||||
}
|
||||
|
||||
InnerRender(): string {
|
||||
const oh = this._oh.data;
|
||||
if (oh === undefined) {
|
||||
return "";
|
||||
}
|
||||
const height = this.getHeight();
|
||||
|
||||
let content = [this._deleteRange]
|
||||
if (height > 2) {
|
||||
content = [this._startTime, this._deleteRange, this._endTime];
|
||||
}
|
||||
|
||||
return new Combine(content)
|
||||
.SetClass("oh-timerange-inner")
|
||||
.Render();
|
||||
}
|
||||
|
||||
private getHeight(): number {
|
||||
const oh = this._oh.data;
|
||||
|
||||
let endhour = oh.endHour;
|
||||
if (oh.endHour == 0 && oh.endMinutes == 0) {
|
||||
endhour = 24;
|
||||
}
|
||||
const height = (endhour - oh.startHour + ((oh.endMinutes - oh.startMinutes) / 60));
|
||||
return height;
|
||||
}
|
||||
|
||||
protected InnerUpdate(el: HTMLElement) {
|
||||
if (el == null) {
|
||||
return;
|
||||
}
|
||||
const oh = this._oh.data;
|
||||
if (oh === undefined) {
|
||||
return;
|
||||
}
|
||||
|
||||
// The header cell containing monday, tuesday, ...
|
||||
const table = document.getElementById(this._tableId) as HTMLTableElement;
|
||||
|
||||
const bodyRect = document.body.getBoundingClientRect();
|
||||
const rangeStart = table.rows[1].cells[1].getBoundingClientRect().top - bodyRect.top;
|
||||
const rangeEnd = table.rows[table.rows.length - 1].cells[1].getBoundingClientRect().bottom - bodyRect.top;
|
||||
|
||||
const pixelsPerHour = (rangeEnd - rangeStart) / 24;
|
||||
|
||||
el.style.top = (pixelsPerHour * OH.startTime(oh)) + "px";
|
||||
el.style.height = (pixelsPerHour * (OH.endTime(oh) - OH.startTime(oh))) + "px";
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -1,169 +0,0 @@
|
|||
import {InputElement} from "../InputElement";
|
||||
import {UIEventSource} from "../../../Logic/UIEventSource";
|
||||
import {UIElement} from "../../UIElement";
|
||||
import {DropDown} from "../DropDown";
|
||||
import Translations from "../../i18n/Translations";
|
||||
import Combine from "../../Base/Combine";
|
||||
import {TextField} from "../TextField";
|
||||
import {OH} from "../../../Logic/OpeningHours";
|
||||
|
||||
export default class PublicHolidayInput extends InputElement<string> {
|
||||
IsSelected: UIEventSource<boolean> = new UIEventSource<boolean>(false);
|
||||
|
||||
private readonly _value: UIEventSource<string>;
|
||||
private readonly _dropdown: UIElement;
|
||||
private readonly _mode: UIEventSource<string>;
|
||||
private readonly _startHour: UIElement;
|
||||
private readonly _endHour: UIElement;
|
||||
|
||||
constructor(value: UIEventSource<string> = new UIEventSource<string>("")) {
|
||||
super();
|
||||
this._value = value;
|
||||
|
||||
const dropdown = new DropDown(
|
||||
Translations.t.general.opening_hours.open_during_ph,
|
||||
[
|
||||
{shown: Translations.t.general.opening_hours.ph_not_known, value: ""},
|
||||
{shown: Translations.t.general.opening_hours.ph_closed, value: "off"},
|
||||
{shown:Translations.t.general.opening_hours.ph_open, value: " "}
|
||||
]
|
||||
);
|
||||
this._dropdown = dropdown.SetStyle("display:inline-block;");
|
||||
this._mode = dropdown.GetValue();
|
||||
this.ListenTo(this._mode);
|
||||
|
||||
const start = new TextField({
|
||||
placeholder: "starthour",
|
||||
htmlType: "time"
|
||||
});
|
||||
const end = new TextField({
|
||||
placeholder: "starthour",
|
||||
htmlType: "time"
|
||||
});
|
||||
this._startHour = start.SetStyle("display:inline-block;");
|
||||
this._endHour = end.SetStyle("display:inline-block;");
|
||||
const self = this;
|
||||
|
||||
this._value.addCallbackAndRun(ph => {
|
||||
if (ph === undefined) {
|
||||
return;
|
||||
}
|
||||
const parsed = PublicHolidayInput.LoadValue(ph);
|
||||
if (parsed === null) {
|
||||
return;
|
||||
}
|
||||
|
||||
dropdown.GetValue().setData(parsed.mode);
|
||||
if (parsed.start) {
|
||||
start.GetValue().setData(parsed.start);
|
||||
}
|
||||
if (parsed.end) {
|
||||
end.GetValue().setData(parsed.end);
|
||||
}
|
||||
|
||||
})
|
||||
|
||||
|
||||
function updateValue() {
|
||||
const phStart = dropdown.GetValue().data;
|
||||
if (phStart === undefined || phStart === "") {
|
||||
// Unknown
|
||||
self._value.setData("");
|
||||
return;
|
||||
}
|
||||
|
||||
if (phStart === " ") {
|
||||
// THey are open, we need to include the start- and enddate
|
||||
const startV = start.GetValue().data;
|
||||
const endV = end.GetValue().data;
|
||||
if (startV === undefined || endV === undefined) {
|
||||
self._value.setData(`PH open`);
|
||||
return;
|
||||
}
|
||||
|
||||
self._value.setData(`PH ${startV}-${endV}`);
|
||||
return;
|
||||
}
|
||||
self._value.setData(`PH ${phStart}`);
|
||||
}
|
||||
|
||||
dropdown.GetValue().addCallbackAndRun(() => {
|
||||
updateValue();
|
||||
});
|
||||
start.GetValue().addCallbackAndRun(() => {
|
||||
updateValue();
|
||||
});
|
||||
end.GetValue().addCallbackAndRun(() => {
|
||||
updateValue();
|
||||
});
|
||||
}
|
||||
|
||||
public static LoadValue(str: string): {
|
||||
mode: string,
|
||||
start?: string,
|
||||
end?: string
|
||||
} {
|
||||
str = str.trim();
|
||||
if (!str.startsWith("PH")) {
|
||||
return null;
|
||||
}
|
||||
|
||||
str = str.trim();
|
||||
if (str === "PH off") {
|
||||
return {
|
||||
mode: "off"
|
||||
}
|
||||
}
|
||||
|
||||
if(str === "PH open"){
|
||||
return {
|
||||
mode: " "
|
||||
}
|
||||
}
|
||||
|
||||
if (!str.startsWith("PH ")) {
|
||||
return null;
|
||||
}
|
||||
try {
|
||||
|
||||
const timerange = OH.parseHHMMRange(str.substring(2));
|
||||
if (timerange === null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return {
|
||||
mode: " ",
|
||||
start: OH.hhmm(timerange.startHour, timerange.startMinutes),
|
||||
end: OH.hhmm(timerange.endHour, timerange.endMinutes),
|
||||
|
||||
}
|
||||
} catch (e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
InnerRender(): string {
|
||||
const mode = this._mode.data;
|
||||
if (mode === " ") {
|
||||
return new Combine([this._dropdown,
|
||||
" ",
|
||||
Translations.t.general.opening_hours.opensAt,
|
||||
" ",
|
||||
this._startHour,
|
||||
" ",
|
||||
Translations.t.general.opening_hours.openTill,
|
||||
" ",
|
||||
this._endHour]).Render();
|
||||
}
|
||||
return this._dropdown.Render();
|
||||
}
|
||||
|
||||
GetValue(): UIEventSource<string> {
|
||||
return this._value;
|
||||
}
|
||||
|
||||
IsValid(t: string): boolean {
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
|
@ -8,7 +8,7 @@ import {UIElement} from "../UIElement";
|
|||
import {UIEventSource} from "../../Logic/UIEventSource";
|
||||
import CombinedInputElement from "./CombinedInputElement";
|
||||
import SimpleDatePicker from "./SimpleDatePicker";
|
||||
import OpeningHoursInput from "./OpeningHours/OpeningHoursInput";
|
||||
import OpeningHoursInput from "../OpeningHours/OpeningHoursInput";
|
||||
import DirectionInput from "./DirectionInput";
|
||||
|
||||
interface TextFieldDef {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue