diff --git a/Docs/SpecialInputElements.md b/Docs/SpecialInputElements.md index c2eb97f9d..ca73d0aca 100644 --- a/Docs/SpecialInputElements.md +++ b/Docs/SpecialInputElements.md @@ -146,12 +146,10 @@ name | doc ------ | ----- options | A JSON-object of type `{ prefix: string, postfix: string }`. -subarg \| doc --------- \| ----- -prefix \| Piece of text that will always be added to the front of the generated opening hours. If the OSM-data does not start with this, it will fail to parse. -postfix \| Piece of text that will always be added to the end of the generated opening hours - - +| subarg | doc | +|---------|-------------------------------------------------------------------------------------------------------------------------------------------------------| +| prefix | Piece of text that will always be added to the front of the generated opening hours. If the OSM-data does not start with this, it will fail to parse. | +| postfix | Piece of text that will always be added to the end of the generated opening hours | ### Example usage diff --git a/public/css/openinghourstable.css b/public/css/openinghourstable.css index 88400363b..731da535e 100644 --- a/public/css/openinghourstable.css +++ b/public/css/openinghourstable.css @@ -78,13 +78,6 @@ box-sizing: border-box; } -.oh-timecell-0 { - border-left: 10px solid rgba(0, 0, 0, 0); -} - -.oh-timecell-6 { - border-right: 10px solid rgba(0, 0, 0, 0); -} .oh-timecol-selected { border-right: var(--catch-detail-color); diff --git a/src/Logic/State/UserSettingsMetaTagging.ts b/src/Logic/State/UserSettingsMetaTagging.ts index 6e568c5c3..33a5ae85b 100644 --- a/src/Logic/State/UserSettingsMetaTagging.ts +++ b/src/Logic/State/UserSettingsMetaTagging.ts @@ -1,42 +1,14 @@ import { Utils } from "../../Utils" /** This code is autogenerated - do not edit. Edit ./assets/layers/usersettings/usersettings.json instead */ export class ThemeMetaTagging { - public static readonly themeName = "usersettings" + public static readonly themeName = "usersettings" - public metaTaggging_for_usersettings(feat: { properties: Record }) { - Utils.AddLazyProperty(feat.properties, "_mastodon_candidate_md", () => - feat.properties._description - .match(/\[[^\]]*\]\((.*(mastodon|en.osm.town).*)\).*/) - ?.at(1) - ) - Utils.AddLazyProperty( - feat.properties, - "_d", - () => feat.properties._description?.replace(/</g, "<")?.replace(/>/g, ">") ?? "" - ) - Utils.AddLazyProperty(feat.properties, "_mastodon_candidate_a", () => - ((feat) => { - const e = document.createElement("div") - e.innerHTML = feat.properties._d - return Array.from(e.getElementsByTagName("a")).filter( - (a) => a.href.match(/mastodon|en.osm.town/) !== null - )[0]?.href - })(feat) - ) - Utils.AddLazyProperty(feat.properties, "_mastodon_link", () => - ((feat) => { - const e = document.createElement("div") - e.innerHTML = feat.properties._d - return Array.from(e.getElementsByTagName("a")).filter( - (a) => a.getAttribute("rel")?.indexOf("me") >= 0 - )[0]?.href - })(feat) - ) - Utils.AddLazyProperty( - feat.properties, - "_mastodon_candidate", - () => feat.properties._mastodon_candidate_md ?? feat.properties._mastodon_candidate_a - ) - feat.properties["__current_backgroun"] = "initial_value" - } -} + public metaTaggging_for_usersettings(feat: {properties: Record}) { + Utils.AddLazyProperty(feat.properties, '_mastodon_candidate_md', () => feat.properties._description.match(/\[[^\]]*\]\((.*(mastodon|en.osm.town).*)\).*/)?.at(1) ) + Utils.AddLazyProperty(feat.properties, '_d', () => feat.properties._description?.replace(/</g,'<')?.replace(/>/g,'>') ?? '' ) + Utils.AddLazyProperty(feat.properties, '_mastodon_candidate_a', () => (feat => {const e = document.createElement('div');e.innerHTML = feat.properties._d;return Array.from(e.getElementsByTagName("a")).filter(a => a.href.match(/mastodon|en.osm.town/) !== null)[0]?.href }) (feat) ) + Utils.AddLazyProperty(feat.properties, '_mastodon_link', () => (feat => {const e = document.createElement('div');e.innerHTML = feat.properties._d;return Array.from(e.getElementsByTagName("a")).filter(a => a.getAttribute("rel")?.indexOf('me') >= 0)[0]?.href})(feat) ) + Utils.AddLazyProperty(feat.properties, '_mastodon_candidate', () => feat.properties._mastodon_candidate_md ?? feat.properties._mastodon_candidate_a ) + feat.properties['__current_backgroun'] = 'initial_value' + } +} \ No newline at end of file diff --git a/src/UI/Input/DropDown.ts b/src/UI/Input/DropDown.ts deleted file mode 100644 index f035da10d..000000000 --- a/src/UI/Input/DropDown.ts +++ /dev/null @@ -1,104 +0,0 @@ -import { InputElement } from "./InputElement" -import Translations from "../i18n/Translations" -import { UIEventSource } from "../../Logic/UIEventSource" -import BaseUIElement from "../BaseUIElement" - -/** - * @deprecated - */ -export class DropDown extends InputElement { - private static _nextDropdownId = 0 - - private readonly _element: HTMLElement - - private readonly _value: UIEventSource - private readonly _values: { value: T; shown: string | BaseUIElement }[] - - /** - * - * const dropdown = new DropDown("test",[{value: 42, shown: "the answer"}]) - * dropdown.GetValue().data // => 42 - */ - constructor( - label: string | BaseUIElement, - values: { value: T; shown: string | BaseUIElement }[], - value: UIEventSource = undefined, - options?: { - select_class?: string - } - ) { - super() - value = value ?? new UIEventSource(values[0].value) - this._value = value - this._values = values - if (values.length <= 1) { - return - } - - const id = DropDown._nextDropdownId - DropDown._nextDropdownId++ - - const el = document.createElement("form") - this._element = el - el.id = "dropdown" + id - - { - const labelEl = Translations.W(label)?.ConstructElement() - if (labelEl !== undefined) { - const labelHtml = document.createElement("label") - labelHtml.appendChild(labelEl) - labelHtml.htmlFor = el.id - el.appendChild(labelHtml) - } - } - - options = options ?? {} - options.select_class = - options.select_class ?? "w-full bg-indigo-100 p-1 rounded hover:bg-indigo-200" - - { - const select = document.createElement("select") - select.classList.add(...(options.select_class.split(" ") ?? [])) - for (let i = 0; i < values.length; i++) { - const option = document.createElement("option") - option.value = "" + i - option.appendChild(Translations.W(values[i].shown).ConstructElement()) - select.appendChild(option) - } - el.appendChild(select) - - select.onchange = () => { - const index = select.selectedIndex - value.setData(values[index].value) - } - - value.addCallbackAndRun((selected) => { - for (let i = 0; i < values.length; i++) { - const value = values[i].value - if (value === selected) { - select.selectedIndex = i - } - } - }) - } - - this.onClick(() => {}) // by registering a click, the click event is consumed and doesn't bubble further to other elements, e.g. checkboxes - } - - GetValue(): UIEventSource { - return this._value - } - - IsValid(t: T): boolean { - for (const value of this._values) { - if (value.value === t) { - return true - } - } - return false - } - - protected InnerConstructElement(): HTMLElement { - return this._element - } -} diff --git a/src/UI/InputElement/Helpers/OpeningHours/OHCell.svelte b/src/UI/InputElement/Helpers/OpeningHours/OHCell.svelte new file mode 100644 index 000000000..85aa89990 --- /dev/null +++ b/src/UI/InputElement/Helpers/OpeningHours/OHCell.svelte @@ -0,0 +1,64 @@ + + + diff --git a/src/UI/InputElement/Helpers/OpeningHours/OHTable.svelte b/src/UI/InputElement/Helpers/OpeningHours/OHTable.svelte new file mode 100644 index 000000000..a95f1d383 --- /dev/null +++ b/src/UI/InputElement/Helpers/OpeningHours/OHTable.svelte @@ -0,0 +1,238 @@ + + + + + + + {#each days as wd} + + + {/each} + + + + + + + {/each} + + + + {#each range(24) as h} + + + {#each range(7) as wd} + startSelection(wd, h)} on:end={() => endSelection(wd, h)} + on:move={() => moved(wd, h)} on:clear={() => clearSelection()} /> + {/each} + + + + {#if h === 23} + + + {/each} + +
+ + + +
+ {#if h < 23} + {h + 1}:00 + {/if} +
+ {/if} + {#each range(7) as wd} + startSelection(wd, h)} on:end={() => endSelection(wd, h)} + on:move={() => moved(wd, h)} on:clear={() => clearSelection()} /> + {/each} +
+ diff --git a/src/UI/InputElement/Helpers/OpeningHoursInput.svelte b/src/UI/InputElement/Helpers/OpeningHoursInput.svelte index de13ff8ba..068a7503c 100644 --- a/src/UI/InputElement/Helpers/OpeningHoursInput.svelte +++ b/src/UI/InputElement/Helpers/OpeningHoursInput.svelte @@ -4,12 +4,39 @@ */ import { UIEventSource } from "../../../Logic/UIEventSource" import ToSvelte from "../../Base/ToSvelte.svelte" - import OpeningHoursInput from "../../OpeningHours/OpeningHoursInput" + import OpeningHoursInput from "../../OpeningHours/OpeningHoursState" import PublicHolidaySelector from "../../OpeningHours/PublicHolidaySelector.svelte" + import OHTable from "./OpeningHours/OHTable.svelte" + import OpeningHoursState from "../../OpeningHours/OpeningHoursState" + import Popup from "../../Base/Popup.svelte" export let value: UIEventSource - export let phSelectorValue = new UIEventSource("") - + export let args: string + let prefix = "" + let postfix = "" + if (args) { + try { - - + const data = JSON.stringify(args) + if (data["prefix"]) { + prefix = data["prefix"] + } + if (data["postfix"]) { + postfix = data["postfix"] + } + } catch (e) { + console.error("Could not parse arguments") + } + } + + const state = new OpeningHoursState(value) + let expanded = new UIEventSource(false) + + + +
+ +
+
+ + diff --git a/src/UI/InputElement/InputHelper.svelte b/src/UI/InputElement/InputHelper.svelte index 2e789d36d..8a8f84466 100644 --- a/src/UI/InputElement/InputHelper.svelte +++ b/src/UI/InputElement/InputHelper.svelte @@ -7,7 +7,6 @@ import { UIEventSource } from "../../Logic/UIEventSource" import type { ValidatorType } from "./Validators" import InputHelpers from "./InputHelpers" - import ToSvelte from "../Base/ToSvelte.svelte" import type { Feature } from "geojson" import ImageHelper from "./Helpers/ImageHelper.svelte" import TranslationInput from "./Helpers/TranslationInput.svelte" @@ -19,7 +18,6 @@ import OpeningHoursInput from "./Helpers/OpeningHoursInput.svelte" import SlopeInput from "./Helpers/SlopeInput.svelte" import type { SpecialVisualizationState } from "../SpecialVisualization" - import WikidataInput from "./Helpers/WikidataInput.svelte" import WikidataInputHelper from "./WikidataInputHelper.svelte" export let type: ValidatorType @@ -48,7 +46,7 @@ {:else if type === "simple_tag"} {:else if type === "opening_hours"} - + {:else if type === "slope"} {:else if type === "wikidata"} diff --git a/src/UI/OpeningHours/OpeningHours.ts b/src/UI/OpeningHours/OpeningHours.ts index 10098ffcf..d664a86fd 100644 --- a/src/UI/OpeningHours/OpeningHours.ts +++ b/src/UI/OpeningHours/OpeningHours.ts @@ -859,6 +859,9 @@ This list will be sorted return ranges } + public static isSame(a: OpeningHour, b: OpeningHour){ + return a.weekday === b.weekday && a.startHour === b.startHour && a.startMinutes === b.startMinutes && a.endHour === b.endHour && a.endMinutes === b.endMinutes + } private static multiply( weekdays: number[], timeranges: { diff --git a/src/UI/OpeningHours/OpeningHoursPicker.ts b/src/UI/OpeningHours/OpeningHoursPicker.ts deleted file mode 100644 index 40eedcaa6..000000000 --- a/src/UI/OpeningHours/OpeningHoursPicker.ts +++ /dev/null @@ -1,33 +0,0 @@ -import { UIEventSource } from "../../Logic/UIEventSource" -import OpeningHoursPickerTable from "./OpeningHoursPickerTable" -import { OH, OpeningHour } from "./OpeningHours" -import { InputElement } from "../Input/InputElement" - -export default class OpeningHoursPicker extends InputElement { - private readonly _ohs: UIEventSource - private readonly _backgroundTable: OpeningHoursPickerTable - - constructor(ohs: UIEventSource = new UIEventSource([])) { - super() - this._ohs = ohs - - ohs.addCallback((oh) => { - ohs.setData(OH.MergeTimes(oh)) - }) - - this._backgroundTable = new OpeningHoursPickerTable(this._ohs) - this._backgroundTable.ConstructElement() - } - - GetValue(): UIEventSource { - return this._ohs - } - - IsValid(_: OpeningHour[]): boolean { - return true - } - - protected InnerConstructElement(): HTMLElement { - return this._backgroundTable.ConstructElement() - } -} diff --git a/src/UI/OpeningHours/OpeningHoursPickerTable.ts b/src/UI/OpeningHours/OpeningHoursPickerTable.ts deleted file mode 100644 index 0e660f714..000000000 --- a/src/UI/OpeningHours/OpeningHoursPickerTable.ts +++ /dev/null @@ -1,332 +0,0 @@ -/** - * This is the base-table which is selectable by hovering over it. - * It will genarate the currently selected opening hour. - */ -import { UIEventSource } from "../../Logic/UIEventSource" -import { Utils } from "../../Utils" -import { OpeningHour } from "./OpeningHours" -import { InputElement } from "../Input/InputElement" -import Translations from "../i18n/Translations" -import { Translation } from "../i18n/Translation" -import { FixedUiElement } from "../Base/FixedUiElement" -import { VariableUiElement } from "../Base/VariableUIElement" -import Combine from "../Base/Combine" -import OpeningHoursRange from "./OpeningHoursRange" - -export default class OpeningHoursPickerTable extends InputElement { - public static readonly days: Translation[] = [ - 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, - ] - /* - These html-elements are an overlay over the table columns and act as a host for the ranges in the weekdays - */ - public readonly weekdayElements: HTMLElement[] = Utils.TimesT(7, () => - document.createElement("div") - ) - private readonly source: UIEventSource - - constructor(source?: UIEventSource) { - super() - this.source = source ?? new UIEventSource([]) - this.SetClass("w-full block") - } - - IsValid(_: OpeningHour[]): boolean { - return true - } - - GetValue(): UIEventSource { - return this.source - } - - protected InnerConstructElement(): HTMLElement { - const table = document.createElement("table") - table.classList.add("oh-table") - table.classList.add("no-weblate") - table.classList.add("relative") // Workaround for webkit-based viewers, see #1019 - - const cellHeightInPx = 14 - - const headerRow = document.createElement("tr") - headerRow.appendChild(document.createElement("th")) - headerRow.classList.add("relative") - for (let i = 0; i < OpeningHoursPickerTable.days.length; i++) { - let weekday = OpeningHoursPickerTable.days[i].Clone() - const cell = document.createElement("th") - cell.style.width = "14%" - cell.appendChild(weekday.ConstructElement()) - - const fullColumnSpan = this.weekdayElements[i] - fullColumnSpan.classList.add("w-full", "relative") - - // We need to round! The table height is rounded as following, we use this to calculate the actual number of pixels afterwards - fullColumnSpan.style.height = cellHeightInPx * 48 + "px" - - const ranges = new VariableUiElement( - this.source - .map((ohs) => (ohs ?? []).filter((oh: OpeningHour) => oh.weekday === i)) - .map((ohsForToday) => { - return new Combine( - ohsForToday.map( - (oh) => - new OpeningHoursRange(oh, () => { - this.source.data.splice(this.source.data.indexOf(oh), 1) - this.source.ping() - }) - ) - ) - }) - ) - fullColumnSpan.appendChild(ranges.ConstructElement()) - - const fullColumnSpanWrapper = document.createElement("div") - fullColumnSpanWrapper.classList.add("absolute") - fullColumnSpanWrapper.style.zIndex = "10" - fullColumnSpanWrapper.style.width = "13.5%" - fullColumnSpanWrapper.style.pointerEvents = "none" - - fullColumnSpanWrapper.appendChild(fullColumnSpan) - - cell.appendChild(fullColumnSpanWrapper) - headerRow.appendChild(cell) - } - - table.appendChild(headerRow) - - const self = this - for (let h = 0; h < 24; h++) { - const hs = Utils.TwoDigits(h) - const firstCell = document.createElement("td") - firstCell.rowSpan = 2 - firstCell.classList.add("oh-left-col", "oh-timecell-full", "border-box") - firstCell.appendChild(new FixedUiElement(hs + ":00").ConstructElement()) - - const evenRow = document.createElement("tr") - evenRow.appendChild(firstCell) - - for (let weekday = 0; weekday < 7; weekday++) { - const cell = document.createElement("td") - cell.classList.add("oh-timecell", "oh-timecell-full", `oh-timecell-${weekday}`) - evenRow.appendChild(cell) - } - evenRow.style.height = cellHeightInPx + "px" - evenRow.style.maxHeight = evenRow.style.height - evenRow.style.minHeight = evenRow.style.height - table.appendChild(evenRow) - - const oddRow = document.createElement("tr") - - for (let weekday = 0; weekday < 7; weekday++) { - const cell = document.createElement("td") - cell.classList.add("oh-timecell", "oh-timecell-half", `oh-timecell-${weekday}`) - oddRow.appendChild(cell) - } - oddRow.style.minHeight = evenRow.style.height - oddRow.style.maxHeight = evenRow.style.height - - table.appendChild(oddRow) - } - - /**** Event handling below ***/ - - 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() - } - } - } - - return table - } -} diff --git a/src/UI/OpeningHours/OpeningHoursRange.ts b/src/UI/OpeningHours/OpeningHoursRange.ts index 45e210cd2..c26af273a 100644 --- a/src/UI/OpeningHours/OpeningHoursRange.ts +++ b/src/UI/OpeningHours/OpeningHoursRange.ts @@ -38,7 +38,7 @@ export default class OpeningHoursRange extends BaseUIElement { }) let content: BaseUIElement - if (height > 2) { + if (height > 3) { content = new Combine([startTime, deleteRange, endTime]).SetClass( "flex flex-col h-full justify-between" ) @@ -55,6 +55,10 @@ export default class OpeningHoursRange extends BaseUIElement { return el } + /** + * Gets the relative height, in number of hours to display + * Range: ]0 - 24] + */ private getHeight(): number { const oh = this._oh diff --git a/src/UI/OpeningHours/OpeningHoursInput.ts b/src/UI/OpeningHours/OpeningHoursState.ts similarity index 61% rename from src/UI/OpeningHours/OpeningHoursInput.ts rename to src/UI/OpeningHours/OpeningHoursState.ts index 25e33e02f..1d5dccc6c 100644 --- a/src/UI/OpeningHours/OpeningHoursInput.ts +++ b/src/UI/OpeningHours/OpeningHoursState.ts @@ -3,30 +3,19 @@ * Keeps track of unparsed rules * Exports everything conveniently as a string, for direct use */ -import OpeningHoursPicker from "./OpeningHoursPicker" import { Store, UIEventSource } from "../../Logic/UIEventSource" -import { VariableUiElement } from "../Base/VariableUIElement" -import Combine from "../Base/Combine" -import { FixedUiElement } from "../Base/FixedUiElement" import { OH, OpeningHour } from "./OpeningHours" -import { InputElement } from "../Input/InputElement" -import Translations from "../i18n/Translations" -import BaseUIElement from "../BaseUIElement" -import SvelteUIElement from "../Base/SvelteUIElement" -import PublicHolidaySelector from "./PublicHolidaySelector.svelte" -export default class OpeningHoursInput extends InputElement { - private readonly _value: UIEventSource - private readonly _element: BaseUIElement +export default class OpeningHoursState { + public readonly normalOhs: UIEventSource + public readonly leftoverRules: Store + public readonly phSelectorValue: UIEventSource constructor( value: UIEventSource = new UIEventSource(""), - phSelectorValue: UIEventSource = new UIEventSource(undefined), prefix = "", - postfix = "" + postfix = "", ) { - super() - this._value = value let valueWithoutPrefix = value if (prefix !== "" && postfix !== "") { valueWithoutPrefix = value.sync( @@ -55,11 +44,11 @@ export default class OpeningHoursInput extends InputElement { } return prefix + noPrefix + postfix - } + }, ) } - const leftoverRules: Store = valueWithoutPrefix.map((str) => { + this.leftoverRules = valueWithoutPrefix.map((str) => { if (str === undefined) { return [] } @@ -89,25 +78,25 @@ export default class OpeningHoursInput extends InputElement { break } } + this.phSelectorValue = new UIEventSource(ph ?? "") - phSelectorValue.set(ph ?? "") // Note: MUST be bound AFTER the leftover rules! - const rulesFromOhPicker: UIEventSource = valueWithoutPrefix.sync( + this.normalOhs = valueWithoutPrefix.sync( (str) => { return OH.Parse(str) }, - [leftoverRules, phSelectorValue], + [this.leftoverRules, this.phSelectorValue], (rules, oldString) => { // We always add a ';', to easily add new rules. We remove the ';' again at the end of the function // Important: spaces are _not_ allowed after a ';' as it'll destabilize the parsing! let str = OH.ToString(rules) + ";" - const ph = phSelectorValue.data + const ph = this.phSelectorValue.data if (ph) { str += ph + ";" } - str += leftoverRules.data.join(";") + ";" + str += this.leftoverRules.data.join(";") + ";" str = str.trim() while (str.endsWith(";")) { @@ -122,40 +111,24 @@ export default class OpeningHoursInput extends InputElement { return oldString // We pass a reference to the old string to stabilize the EventSource } return str - } + }, ) + /* + const 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}
`).join("")).SetClass( + "subtle" + ), + ]) + }) + )*/ - const 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}
`).join("")).SetClass( - "subtle" - ), - ]) - }) - ) - const ohPicker = new OpeningHoursPicker(rulesFromOhPicker) - - this._element = new Combine([ - leftoverWarning, - ohPicker, - ]) } - GetValue(): UIEventSource { - return this._value - } - - IsValid(_: string): boolean { - return true - } - - protected InnerConstructElement(): HTMLElement { - return this._element.ConstructElement() - } } diff --git a/src/UI/Test.svelte b/src/UI/Test.svelte index 0703c80bd..080c36b02 100644 --- a/src/UI/Test.svelte +++ b/src/UI/Test.svelte @@ -1,4 +1,40 @@ -
+
+ +