More work on the opening hours picker
This commit is contained in:
parent
4d139b45e6
commit
6563298d16
15 changed files with 321 additions and 100 deletions
|
@ -207,7 +207,9 @@ export class InitUiElements {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
new GeoLocationHandler().AttachTo("geolocate-button");
|
new GeoLocationHandler()
|
||||||
|
.SetStyle(`position:relative;display:block;border: solid 2px #0005;cursor: pointer; z-index: 999; /*Just below leaflets zoom*/background-color: white;border-radius: 5px;width: 43px;height: 43px;`)
|
||||||
|
.AttachTo("geolocate-button");
|
||||||
State.state.locationControl.ping();
|
State.state.locationControl.ping();
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -8,7 +8,7 @@ export interface OpeningHour {
|
||||||
endMinutes: number
|
endMinutes: number
|
||||||
}
|
}
|
||||||
|
|
||||||
export class OpeningHourUtils {
|
export class OH {
|
||||||
|
|
||||||
|
|
||||||
private static readonly days = ["Mo", "Tu", "We", "Th", "Fr", "Sa", "Su"]
|
private static readonly days = ["Mo", "Tu", "We", "Th", "Fr", "Sa", "Su"]
|
||||||
|
@ -23,19 +23,53 @@ export class OpeningHourUtils {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static ToString(ohs: OpeningHour[]) {
|
public static ToString(ohs: OpeningHour[]) {
|
||||||
const parts = [];
|
if (ohs.length == 0) {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
const partsPerWeekday: string [][] = [[], [], [], [], [], [], []];
|
||||||
|
|
||||||
function hhmm(h, m) {
|
function hhmm(h, m) {
|
||||||
return Utils.TwoDigits(h) + ":" + Utils.TwoDigits(m);
|
return Utils.TwoDigits(h) + ":" + Utils.TwoDigits(m);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (const oh of ohs) {
|
for (const oh of ohs) {
|
||||||
parts.push(
|
partsPerWeekday[oh.weekday].push(hhmm(oh.startHour, oh.startMinutes) + "-" + hhmm(oh.endHour, oh.endMinutes));
|
||||||
OpeningHourUtils.days[oh.weekday] + " " + hhmm(oh.startHour, oh.startMinutes) + "-" + hhmm(oh.endHour, oh.endMinutes)
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return parts.join("; ")+";"
|
const stringPerWeekday = partsPerWeekday.map(parts => parts.sort().join(", "));
|
||||||
|
|
||||||
|
const rules = [];
|
||||||
|
|
||||||
|
let rangeStart = 0;
|
||||||
|
let rangeEnd = 0;
|
||||||
|
|
||||||
|
function pushRule(){
|
||||||
|
const rule = stringPerWeekday[rangeStart];
|
||||||
|
if(rule === ""){
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (rangeStart == (rangeEnd - 1)) {
|
||||||
|
rules.push(
|
||||||
|
`${OH.days[rangeStart]} ${rule}`
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
rules.push(
|
||||||
|
`${OH.days[rangeStart]}-${OH.days[rangeEnd-1]} ${rule}`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (; rangeEnd < 7; rangeEnd++) {
|
||||||
|
|
||||||
|
if (stringPerWeekday[rangeStart] != stringPerWeekday[rangeEnd]) {
|
||||||
|
pushRule();
|
||||||
|
rangeStart = rangeEnd
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
pushRule();
|
||||||
|
|
||||||
|
return rules.join("; ") + ";"
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -62,32 +96,32 @@ export class OpeningHourUtils {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
if (OpeningHourUtils.startTimeLiesInRange(maybeAdd, guard) && OpeningHourUtils.endTimeLiesInRange(maybeAdd, guard)) {
|
if (OH.startTimeLiesInRange(maybeAdd, guard) && OH.endTimeLiesInRange(maybeAdd, guard)) {
|
||||||
// Guard fully covers 'maybeAdd': we can safely ignore maybeAdd
|
// Guard fully covers 'maybeAdd': we can safely ignore maybeAdd
|
||||||
doAddEntry = false;
|
doAddEntry = false;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (OpeningHourUtils.startTimeLiesInRange(guard, maybeAdd) && OpeningHourUtils.endTimeLiesInRange(guard, maybeAdd)) {
|
if (OH.startTimeLiesInRange(guard, maybeAdd) && OH.endTimeLiesInRange(guard, maybeAdd)) {
|
||||||
// 'maybeAdd' fully covers Guard - the guard is killed
|
// 'maybeAdd' fully covers Guard - the guard is killed
|
||||||
newList.splice(i, 1);
|
newList.splice(i, 1);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (OpeningHourUtils.startTimeLiesInRange(maybeAdd, guard) || OpeningHourUtils.endTimeLiesInRange(maybeAdd, guard)
|
if (OH.startTimeLiesInRange(maybeAdd, guard) || OH.endTimeLiesInRange(maybeAdd, guard)
|
||||||
|| OpeningHourUtils.startTimeLiesInRange(guard, maybeAdd) || OpeningHourUtils.endTimeLiesInRange(guard, maybeAdd)) {
|
|| OH.startTimeLiesInRange(guard, maybeAdd) || OH.endTimeLiesInRange(guard, maybeAdd)) {
|
||||||
// At this point, the maybeAdd overlaps the guard: we should extend the guard and retest it
|
// At this point, the maybeAdd overlaps the guard: we should extend the guard and retest it
|
||||||
newList.splice(i, 1);
|
newList.splice(i, 1);
|
||||||
let startHour = guard.startHour;
|
let startHour = guard.startHour;
|
||||||
let startMinutes = guard.startMinutes;
|
let startMinutes = guard.startMinutes;
|
||||||
if(OpeningHourUtils.startTime(maybeAdd)<OpeningHourUtils.startTime(guard)){
|
if (OH.startTime(maybeAdd) < OH.startTime(guard)) {
|
||||||
startHour = maybeAdd.startHour;
|
startHour = maybeAdd.startHour;
|
||||||
startMinutes = maybeAdd.startMinutes;
|
startMinutes = maybeAdd.startMinutes;
|
||||||
}
|
}
|
||||||
|
|
||||||
let endHour = guard.endHour;
|
let endHour = guard.endHour;
|
||||||
let endMinutes = guard.endMinutes;
|
let endMinutes = guard.endMinutes;
|
||||||
if(OpeningHourUtils.endTime(maybeAdd)>OpeningHourUtils.endTime(guard)){
|
if (OH.endTime(maybeAdd) > OH.endTime(guard)) {
|
||||||
endHour = maybeAdd.endHour;
|
endHour = maybeAdd.endHour;
|
||||||
endMinutes = maybeAdd.endMinutes;
|
endMinutes = maybeAdd.endMinutes;
|
||||||
}
|
}
|
||||||
|
@ -130,51 +164,128 @@ export class OpeningHourUtils {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static startTimeLiesInRange(checked: OpeningHour, mightLieIn: OpeningHour) {
|
public static startTimeLiesInRange(checked: OpeningHour, mightLieIn: OpeningHour) {
|
||||||
return OpeningHourUtils.startTime(mightLieIn) <= OpeningHourUtils.startTime(checked) &&
|
return OH.startTime(mightLieIn) <= OH.startTime(checked) &&
|
||||||
OpeningHourUtils.startTime(checked) <= OpeningHourUtils.endTime(mightLieIn)
|
OH.startTime(checked) <= OH.endTime(mightLieIn)
|
||||||
}
|
}
|
||||||
|
|
||||||
public static endTimeLiesInRange(checked: OpeningHour, mightLieIn: OpeningHour) {
|
public static endTimeLiesInRange(checked: OpeningHour, mightLieIn: OpeningHour) {
|
||||||
return OpeningHourUtils.startTime(mightLieIn) <= OpeningHourUtils.endTime(checked) &&
|
return OH.startTime(mightLieIn) <= OH.endTime(checked) &&
|
||||||
OpeningHourUtils.endTime(checked) <= OpeningHourUtils.endTime(mightLieIn)
|
OH.endTime(checked) <= OH.endTime(mightLieIn)
|
||||||
}
|
}
|
||||||
|
|
||||||
static Parse(str: string) {
|
private static parseHHMM(hhmm: string): { hours: number, minutes: number } {
|
||||||
if (str === undefined || str === "") {
|
const spl = hhmm.trim().split(":");
|
||||||
|
return {hours: Number(spl[0].trim()), minutes: Number(spl[1].trim())};
|
||||||
|
}
|
||||||
|
|
||||||
|
private static parseHHMMRange(hhmmhhmm: string): {
|
||||||
|
startHour: number,
|
||||||
|
startMinutes: number,
|
||||||
|
endHour: number,
|
||||||
|
endMinutes: number
|
||||||
|
} {
|
||||||
|
const timings = hhmmhhmm.split("-");
|
||||||
|
const start = OH.parseHHMM(timings[0])
|
||||||
|
const end = OH.parseHHMM(timings[1]);
|
||||||
|
return {
|
||||||
|
startHour: start.hours,
|
||||||
|
startMinutes: start.minutes,
|
||||||
|
endHour: end.hours,
|
||||||
|
endMinutes: end.minutes
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static ParseHhmmRanges(hhmms: string): {
|
||||||
|
startHour: number,
|
||||||
|
startMinutes: number,
|
||||||
|
endHour: number,
|
||||||
|
endMinutes: number
|
||||||
|
}[] {
|
||||||
|
return hhmms.split(",")
|
||||||
|
.map(s => s.trim())
|
||||||
|
.filter(str => str !== "")
|
||||||
|
.map(OH.parseHHMMRange)
|
||||||
|
}
|
||||||
|
|
||||||
|
private static ParseWeekday(weekday: string): number {
|
||||||
|
return OH.daysIndexed[weekday.trim().toLowerCase()];
|
||||||
|
}
|
||||||
|
|
||||||
|
private static ParseWeekdayRange(weekdays: string): number[] {
|
||||||
|
const split = weekdays.split("-");
|
||||||
|
if (split.length == 1) {
|
||||||
|
return [OH.ParseWeekday(weekdays)];
|
||||||
|
} else if (split.length == 2) {
|
||||||
|
let start = OH.ParseWeekday(split[0]);
|
||||||
|
let end = OH.ParseWeekday(split[1]);
|
||||||
|
let range = [];
|
||||||
|
for (let i = start; i <= end; i++) {
|
||||||
|
range.push(i);
|
||||||
|
}
|
||||||
|
return range;
|
||||||
|
} else {
|
||||||
|
throw "Invalid format: " + weekdays + " is not a weekdays range"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static ParseWeekdayRanges(weekdays: string): number[] {
|
||||||
|
let ranges = [];
|
||||||
|
let split = weekdays.split(",");
|
||||||
|
for (const weekday of split) {
|
||||||
|
ranges.push(...OH.ParseWeekdayRange(weekday));
|
||||||
|
}
|
||||||
|
return ranges;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static multiply(weekdays: number[], timeranges: { startHour: number, startMinutes: number, endHour: number, endMinutes: number }[]) {
|
||||||
|
const ohs: OpeningHour[] = []
|
||||||
|
for (const timerange of timeranges) {
|
||||||
|
for (const weekday of weekdays) {
|
||||||
|
ohs.push({
|
||||||
|
weekday: weekday,
|
||||||
|
startHour: timerange.startHour, startMinutes: timerange.startMinutes,
|
||||||
|
endHour: timerange.endHour, endMinutes: timerange.endMinutes,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ohs;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ParseRule(rule: string): OpeningHour[] {
|
||||||
|
const split = rule.trim().replace(/, */g, ",").split(" ");
|
||||||
|
if (split.length == 1) {
|
||||||
|
// First, try to parse this rule as a rule without weekdays
|
||||||
|
let timeranges = OH.ParseHhmmRanges(rule);
|
||||||
|
let weekdays = [0, 1, 2, 3, 4, 5, 6];
|
||||||
|
return OH.multiply(weekdays, timeranges);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (split.length == 2) {
|
||||||
|
const weekdays = OH.ParseWeekdayRanges(split[0]);
|
||||||
|
const timeranges = OH.ParseHhmmRanges(split[1]);
|
||||||
|
return OH.multiply(weekdays, timeranges);
|
||||||
|
}
|
||||||
|
throw `Could not parse rule: ${rule} has ${split.length} parts (expected one or two)`;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static Parse(rules: string) {
|
||||||
|
if (rules === undefined || rules === "") {
|
||||||
return []
|
return []
|
||||||
}
|
}
|
||||||
|
|
||||||
const parts = str.toLowerCase().split(";");
|
|
||||||
const ohs = []
|
const ohs = []
|
||||||
|
|
||||||
function parseTime(hhmm) {
|
const split = rules.split(";");
|
||||||
const spl = hhmm.trim().split(":");
|
|
||||||
return [Number(spl[0].trim()), Number(spl[1].trim())]
|
|
||||||
}
|
|
||||||
|
|
||||||
for (const part of parts) {
|
for (const rule of split) {
|
||||||
if(part === ""){
|
if(rule === ""){
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
|
ohs.push(...OH.ParseRule(rule));
|
||||||
const partSplit = part.trim().split(" ");
|
|
||||||
const weekday = OpeningHourUtils.daysIndexed[partSplit[0]]
|
|
||||||
const timings = partSplit[1].split("-");
|
|
||||||
const start = parseTime(timings[0])
|
|
||||||
const end = parseTime(timings[1]);
|
|
||||||
|
|
||||||
const oh: OpeningHour = {
|
|
||||||
weekday: weekday,
|
|
||||||
startHour: start[0],
|
|
||||||
startMinutes: start[1],
|
|
||||||
endHour: end[0],
|
|
||||||
endMinutes: end[1],
|
|
||||||
}
|
|
||||||
ohs.push(oh);
|
|
||||||
|
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.error("Could not parse opening hours part", part, ", skipping it due to ", e)
|
console.error("Could not parse ", rule, ": ", e)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -9,6 +9,10 @@ export class UIEventSource<T>{
|
||||||
|
|
||||||
|
|
||||||
public addCallback(callback: ((latestData: T) => void)): UIEventSource<T> {
|
public addCallback(callback: ((latestData: T) => void)): UIEventSource<T> {
|
||||||
|
if(callback === console.log){
|
||||||
|
// This ^^^ actually works!
|
||||||
|
throw "Don't add console.log directly as a callback - you'll won't be able to find it afterwards. Wrap it in a lambda instead."
|
||||||
|
}
|
||||||
this._callbacks.push(callback);
|
this._callbacks.push(callback);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
5
State.ts
5
State.ts
|
@ -111,9 +111,9 @@ export default class State {
|
||||||
* The location as delivered by the GPS
|
* The location as delivered by the GPS
|
||||||
*/
|
*/
|
||||||
public currentGPSLocation: UIEventSource<{
|
public currentGPSLocation: UIEventSource<{
|
||||||
latlng: number,
|
latlng: {lat:number, lon:number},
|
||||||
accuracy: number
|
accuracy: number
|
||||||
}> = new UIEventSource<{ latlng: number, accuracy: number }>(undefined);
|
}> = new UIEventSource<{ latlng: {lat:number, lon:number}, accuracy: number }>(undefined);
|
||||||
public layoutDefinition: string;
|
public layoutDefinition: string;
|
||||||
public installedThemes: UIEventSource<{ layout: Layout; definition: string }[]>;
|
public installedThemes: UIEventSource<{ layout: Layout; definition: string }[]>;
|
||||||
|
|
||||||
|
@ -139,7 +139,6 @@ export default class State {
|
||||||
return ("" + fl).substr(0, 8);
|
return ("" + fl).substr(0, 8);
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
this.zoom = asFloat(
|
this.zoom = asFloat(
|
||||||
QueryParameters.GetQueryParameter("z", "" + layoutToUse.startzoom)
|
QueryParameters.GetQueryParameter("z", "" + layoutToUse.startzoom)
|
||||||
.syncWith(LocalStorageSource.Get("zoom"), true));
|
.syncWith(LocalStorageSource.Get("zoom"), true));
|
||||||
|
|
|
@ -35,8 +35,6 @@ export default class InputElementMap<T, X> extends InputElement<X> {
|
||||||
}), extraSources, x => {
|
}), extraSources, x => {
|
||||||
return fromX(x);
|
return fromX(x);
|
||||||
});
|
});
|
||||||
this._value.addCallback(console.log)
|
|
||||||
this.IsSelected.addCallback(s => console.log("Is selected?", s))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
GetValue(): UIEventSource<X> {
|
GetValue(): UIEventSource<X> {
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import {UIElement} from "../../UIElement";
|
import {UIElement} from "../../UIElement";
|
||||||
import {InputElement} from "../InputElement";
|
import {InputElement} from "../InputElement";
|
||||||
import {OpeningHour, OpeningHourUtils} from "../../../Logic/OpeningHours";
|
import {OpeningHour, OH} from "../../../Logic/OpeningHours";
|
||||||
import {UIEventSource} from "../../../Logic/UIEventSource";
|
import {UIEventSource} from "../../../Logic/UIEventSource";
|
||||||
import OpeningHoursPickerTable from "./OpeningHoursPickerTable";
|
import OpeningHoursPickerTable from "./OpeningHoursPickerTable";
|
||||||
import OpeningHoursRange from "./OpeningHoursRange";
|
import OpeningHoursRange from "./OpeningHoursRange";
|
||||||
|
@ -17,23 +17,16 @@ export default class OpeningHoursPicker extends InputElement<OpeningHour[]> {
|
||||||
constructor(ohs: UIEventSource<OpeningHour[]> = new UIEventSource<OpeningHour[]>([])) {
|
constructor(ohs: UIEventSource<OpeningHour[]> = new UIEventSource<OpeningHour[]>([])) {
|
||||||
super();
|
super();
|
||||||
this._ohs = ohs;
|
this._ohs = ohs;
|
||||||
this._backgroundTable = new OpeningHoursPickerTable(this._weekdays);
|
this._backgroundTable = new OpeningHoursPickerTable(this._weekdays, this._ohs);
|
||||||
const self = this;
|
const self = this;
|
||||||
|
|
||||||
this._backgroundTable.GetValue().addCallback(oh => {
|
|
||||||
if (oh) {
|
|
||||||
ohs.data.push(oh);
|
|
||||||
ohs.ping();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
this._ohs.addCallback(ohs => {
|
this._ohs.addCallback(ohs => {
|
||||||
self._ohs.setData(OpeningHourUtils.MergeTimes(ohs));
|
self._ohs.setData(OH.MergeTimes(ohs));
|
||||||
})
|
})
|
||||||
|
|
||||||
ohs.addCallback(ohs => {
|
ohs.addCallbackAndRun(ohs => {
|
||||||
const perWeekday: UIElement[][] = [];
|
const perWeekday: UIElement[][] = [];
|
||||||
|
|
||||||
for (let i = 0; i < 7; i++) {
|
for (let i = 0; i < 7; i++) {
|
||||||
perWeekday[i] = [];
|
perWeekday[i] = [];
|
||||||
}
|
}
|
||||||
|
@ -41,7 +34,7 @@ export default class OpeningHoursPicker extends InputElement<OpeningHour[]> {
|
||||||
for (const oh of ohs) {
|
for (const oh of ohs) {
|
||||||
const source = new UIEventSource<OpeningHour>(oh)
|
const source = new UIEventSource<OpeningHour>(oh)
|
||||||
source.addCallback(_ => {
|
source.addCallback(_ => {
|
||||||
self._ohs.setData(OpeningHourUtils.MergeTimes(self._ohs.data))
|
self._ohs.setData(OH.MergeTimes(self._ohs.data))
|
||||||
})
|
})
|
||||||
const r = new OpeningHoursRange(source);
|
const r = new OpeningHoursRange(source);
|
||||||
perWeekday[oh.weekday].push(r);
|
perWeekday[oh.weekday].push(r);
|
||||||
|
@ -52,7 +45,6 @@ export default class OpeningHoursPicker extends InputElement<OpeningHour[]> {
|
||||||
}
|
}
|
||||||
self._weekdays.ping();
|
self._weekdays.ping();
|
||||||
|
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,19 +8,19 @@ import {UIElement} from "../../UIElement";
|
||||||
* This is the base-table which is selectable by hovering over it.
|
* This is the base-table which is selectable by hovering over it.
|
||||||
* It will genarate the currently selected opening hour.
|
* It will genarate the currently selected opening hour.
|
||||||
*/
|
*/
|
||||||
export default class OpeningHoursPickerTable extends InputElement<OpeningHour> {
|
export default class OpeningHoursPickerTable extends InputElement<OpeningHour[]> {
|
||||||
public readonly IsSelected: UIEventSource<boolean>;
|
public readonly IsSelected: UIEventSource<boolean>;
|
||||||
private readonly weekdays: UIEventSource<UIElement[]>;
|
private readonly weekdays: UIEventSource<UIElement[]>;
|
||||||
|
|
||||||
public static readonly days = ["Maan", "Din", "Woe", "Don", "Vrij", "Zat", "Zon"];
|
public static readonly days = ["Maan", "Din", "Woe", "Don", "Vrij", "Zat", "Zon"];
|
||||||
|
|
||||||
private readonly source: UIEventSource<OpeningHour>;
|
private readonly source: UIEventSource<OpeningHour[]>;
|
||||||
|
|
||||||
|
|
||||||
constructor(weekdays: UIEventSource<UIElement[]>, source?: UIEventSource<OpeningHour>) {
|
constructor(weekdays: UIEventSource<UIElement[]>, source?: UIEventSource<OpeningHour[]>) {
|
||||||
super(weekdays);
|
super(weekdays);
|
||||||
this.weekdays = weekdays;
|
this.weekdays = weekdays;
|
||||||
this.source = source ?? new UIEventSource<OpeningHour>(undefined);
|
this.source = source ?? new UIEventSource<OpeningHour[]>([]);
|
||||||
this.IsSelected = new UIEventSource<boolean>(false);
|
this.IsSelected = new UIEventSource<boolean>(false);
|
||||||
this.SetStyle("width:100%;height:100%;display:block;");
|
this.SetStyle("width:100%;height:100%;display:block;");
|
||||||
|
|
||||||
|
@ -105,8 +105,9 @@ export default class OpeningHoursPickerTable extends InputElement<OpeningHour> {
|
||||||
oh.endHour = 24;
|
oh.endHour = 24;
|
||||||
oh.endMinutes = 0;
|
oh.endMinutes = 0;
|
||||||
}
|
}
|
||||||
self.source.setData(oh);
|
self.source.data.push(oh);
|
||||||
}
|
}
|
||||||
|
self.source.ping();
|
||||||
|
|
||||||
// Clear the highlighting
|
// Clear the highlighting
|
||||||
for (let i = 1; i < table.rows.length; i++) {
|
for (let i = 1; i < table.rows.length; i++) {
|
||||||
|
@ -229,11 +230,11 @@ export default class OpeningHoursPickerTable extends InputElement<OpeningHour> {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
IsValid(t: OpeningHour): boolean {
|
IsValid(t: OpeningHour[]): boolean {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
GetValue(): UIEventSource<OpeningHour> {
|
GetValue(): UIEventSource<OpeningHour[]> {
|
||||||
return this.source;
|
return this.source;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -26,7 +26,6 @@ export default class OpeningHoursRange extends UIElement {
|
||||||
self.InnerUpdate(el);
|
self.InnerUpdate(el);
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
||||||
this._deleteRange = new FixedUiElement("<img src='./assets/delete.svg'>")
|
this._deleteRange = new FixedUiElement("<img src='./assets/delete.svg'>")
|
||||||
.SetClass("oh-delete-range")
|
.SetClass("oh-delete-range")
|
||||||
.onClick(() => {
|
.onClick(() => {
|
||||||
|
|
|
@ -9,7 +9,7 @@ import {UIEventSource} from "../../Logic/UIEventSource";
|
||||||
import CombinedInputElement from "./CombinedInputElement";
|
import CombinedInputElement from "./CombinedInputElement";
|
||||||
import SimpleDatePicker from "./SimpleDatePicker";
|
import SimpleDatePicker from "./SimpleDatePicker";
|
||||||
import OpeningHoursPicker from "./OpeningHours/OpeningHoursPicker";
|
import OpeningHoursPicker from "./OpeningHours/OpeningHoursPicker";
|
||||||
import {OpeningHour, OpeningHourUtils} from "../../Logic/OpeningHours";
|
import {OpeningHour, OH} from "../../Logic/OpeningHours";
|
||||||
|
|
||||||
interface TextFieldDef {
|
interface TextFieldDef {
|
||||||
name: string,
|
name: string,
|
||||||
|
@ -148,15 +148,17 @@ export default class ValidatedTextField {
|
||||||
"opening_hours",
|
"opening_hours",
|
||||||
"Has extra elements to easily input when a POI is opened",
|
"Has extra elements to easily input when a POI is opened",
|
||||||
(s, country) => true, // TODO
|
(s, country) => true, // TODO
|
||||||
str => str, // TODO reformat with opening_hours.js
|
str => str,
|
||||||
(value) => {
|
(value) => {
|
||||||
const input = new InputElementMap<OpeningHour[], string>(new OpeningHoursPicker(),
|
|
||||||
|
const sourceMapped = value.map(OH.Parse, [], OH.ToString);
|
||||||
|
|
||||||
|
const input = new InputElementMap<OpeningHour[], string>(new OpeningHoursPicker(sourceMapped),
|
||||||
(a, b) => a === b,
|
(a, b) => a === b,
|
||||||
ohs => OpeningHourUtils.ToString(ohs),
|
ohs => OH.ToString(ohs),
|
||||||
str => OpeningHourUtils.Parse(str)
|
str => OH.Parse(str)
|
||||||
)
|
)
|
||||||
input.GetValue().addCallback(latest => {
|
input.GetValue().addCallback(latest => {
|
||||||
console.log(latest);
|
|
||||||
value.setData(latest);
|
value.setData(latest);
|
||||||
})
|
})
|
||||||
return input;
|
return input;
|
||||||
|
|
|
@ -71,8 +71,8 @@ export class TagRendering extends UIElement implements TagDependantUIElement {
|
||||||
}) {
|
}) {
|
||||||
super(tags);
|
super(tags);
|
||||||
this.ListenTo(Locale.language);
|
this.ListenTo(Locale.language);
|
||||||
this.ListenTo(this._questionSkipped);
|
|
||||||
this.ListenTo(this._editMode);
|
this.ListenTo(this._editMode);
|
||||||
|
this.ListenTo(this._questionSkipped);
|
||||||
this.ListenTo(State.state?.osmConnection?.userDetails);
|
this.ListenTo(State.state?.osmConnection?.userDetails);
|
||||||
|
|
||||||
const self = this;
|
const self = this;
|
||||||
|
|
|
@ -17,13 +17,6 @@ body {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
bottom: 25px;
|
bottom: 25px;
|
||||||
right: 50px;
|
right: 50px;
|
||||||
z-index: 999; /*Just below leaflets zoom*/
|
|
||||||
background-color: white;
|
|
||||||
border-radius: 5px;
|
|
||||||
border: solid 2px #0005;
|
|
||||||
cursor: pointer;
|
|
||||||
width: 43px;
|
|
||||||
height: 43px;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#geolocate-button img {
|
#geolocate-button img {
|
||||||
|
|
|
@ -58,7 +58,7 @@
|
||||||
<div id="centermessage">Loading MapComplete, hang on...</div>
|
<div id="centermessage">Loading MapComplete, hang on...</div>
|
||||||
<div id="top-right"></div>
|
<div id="top-right"></div>
|
||||||
|
|
||||||
<div id="geolocate-button"></div>
|
<span id="geolocate-button"></span>
|
||||||
<div id="leafletDiv"></div>
|
<div id="leafletDiv"></div>
|
||||||
|
|
||||||
<script src="./index.ts"></script>
|
<script src="./index.ts"></script>
|
||||||
|
|
23
test.ts
23
test.ts
|
@ -1,17 +1,30 @@
|
||||||
//*
|
//*
|
||||||
|
import OpeningHoursPicker from "./UI/Input/OpeningHours/OpeningHoursPicker";
|
||||||
|
import {VariableUiElement} from "./UI/Base/VariableUIElement";
|
||||||
|
import {OH} from "./Logic/OpeningHours";
|
||||||
|
|
||||||
import opening_hours from "opening_hours";
|
const picker = new OpeningHoursPicker();
|
||||||
|
new VariableUiElement(picker.GetValue().map(OH.ToString)).AttachTo("extradiv");
|
||||||
|
picker.AttachTo("maindiv");
|
||||||
|
|
||||||
const oh =new opening_hours("mo 09:00-17:00;Tu 09:00-17:00;We 09:00-17:00");
|
|
||||||
console.log(oh)
|
|
||||||
|
|
||||||
/*/
|
window.setTimeout(() => {
|
||||||
|
picker.GetValue().setData([{
|
||||||
|
weekday: 1,
|
||||||
|
startHour: 11,
|
||||||
|
startMinutes: 0,
|
||||||
|
endHour: 17,
|
||||||
|
endMinutes: 0
|
||||||
|
}]);
|
||||||
|
|
||||||
|
}, 1000)
|
||||||
|
/*/
|
||||||
|
|
||||||
|
|
||||||
import {Utils} from "./Utils";
|
import {Utils} from "./Utils";
|
||||||
import {FixedUiElement} from "./UI/Base/FixedUiElement";
|
import {FixedUiElement} from "./UI/Base/FixedUiElement";
|
||||||
|
|
||||||
Utils.generateStats((stats) => {
|
Utils.generateStats((stats) => {
|
||||||
new FixedUiElement(stats).AttachTo('maindiv')
|
new FixedUiElement(stats).AttachTo('maindiv')
|
||||||
})
|
})
|
||||||
//*/
|
//*/
|
123
test/Tag.spec.ts
123
test/Tag.spec.ts
|
@ -1,7 +1,5 @@
|
||||||
import {UIElement} from "../UI/UIElement";
|
import {UIElement} from "../UI/UIElement";
|
||||||
|
|
||||||
UIElement.runningFromConsole = true;
|
UIElement.runningFromConsole = true;
|
||||||
|
|
||||||
import {equal} from "assert";
|
import {equal} from "assert";
|
||||||
import Translation from "../UI/i18n/Translation";
|
import Translation from "../UI/i18n/Translation";
|
||||||
import T from "./TestHelper";
|
import T from "./TestHelper";
|
||||||
|
@ -9,11 +7,10 @@ import {FromJSON} from "../Customizations/JSON/FromJSON";
|
||||||
import {And, Tag} from "../Logic/Tags";
|
import {And, Tag} from "../Logic/Tags";
|
||||||
import Locale from "../UI/i18n/Locale";
|
import Locale from "../UI/i18n/Locale";
|
||||||
import Translations from "../UI/i18n/Translations";
|
import Translations from "../UI/i18n/Translations";
|
||||||
import {TagRenderingOptions} from "../Customizations/TagRenderingOptions";
|
|
||||||
import {UIEventSource} from "../Logic/UIEventSource";
|
import {UIEventSource} from "../Logic/UIEventSource";
|
||||||
import {TagRendering} from "../UI/TagRendering";
|
import {TagRendering} from "../UI/TagRendering";
|
||||||
import {Basemap} from "../Logic/Leaflet/Basemap";
|
import {OH, OpeningHour} from "../Logic/OpeningHours";
|
||||||
import {OpeningHour, OpeningHourUtils} from "../Logic/OpeningHours";
|
|
||||||
|
|
||||||
|
|
||||||
new T([
|
new T([
|
||||||
|
@ -140,7 +137,7 @@ new T([
|
||||||
endMinutes: 0
|
endMinutes: 0
|
||||||
};
|
};
|
||||||
|
|
||||||
const merged = OpeningHourUtils.MergeTimes([oh0, oh1]);
|
const merged = OH.MergeTimes([oh0, oh1]);
|
||||||
const r = merged[0];
|
const r = merged[0];
|
||||||
equal( merged.length, 1);
|
equal( merged.length, 1);
|
||||||
equal(r.startHour,10 );
|
equal(r.startHour,10 );
|
||||||
|
@ -165,12 +162,122 @@ new T([
|
||||||
endMinutes: 0
|
endMinutes: 0
|
||||||
};
|
};
|
||||||
|
|
||||||
const merged = OpeningHourUtils.MergeTimes([oh0, oh1]);
|
const merged = OH.MergeTimes([oh0, oh1]);
|
||||||
const r = merged[0];
|
const r = merged[0];
|
||||||
equal( merged.length, 1);
|
equal( merged.length, 1);
|
||||||
equal(r.startHour,10 );
|
equal(r.startHour,10 );
|
||||||
equal(r.endHour, 12)
|
equal(r.endHour, 12)
|
||||||
|
|
||||||
}
|
}
|
||||||
]
|
],
|
||||||
|
["Parse OH 1",() => {
|
||||||
|
const rules = OH.ParseRule("11:00-19:00");
|
||||||
|
equal(rules.length, 7);
|
||||||
|
equal(rules[0].weekday, 0);
|
||||||
|
equal(rules[0].startHour, 11);
|
||||||
|
equal(rules[3].endHour, 19);
|
||||||
|
|
||||||
|
}],
|
||||||
|
["Parse OH 2",() => {
|
||||||
|
const rules = OH.ParseRule("Mo-Th 11:00-19:00");
|
||||||
|
equal(rules.length, 4);
|
||||||
|
equal(rules[0].weekday, 0);
|
||||||
|
equal(rules[0].startHour, 11);
|
||||||
|
equal(rules[3].endHour, 19);
|
||||||
|
}],
|
||||||
|
["JOIN OH 1",() => {
|
||||||
|
const rules = OH.ToString([
|
||||||
|
{
|
||||||
|
weekday: 0,
|
||||||
|
endHour: 12,
|
||||||
|
endMinutes: 0,
|
||||||
|
startHour: 10,
|
||||||
|
startMinutes: 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
weekday: 0,
|
||||||
|
endHour: 17,
|
||||||
|
endMinutes: 0,
|
||||||
|
startHour: 13,
|
||||||
|
startMinutes: 0
|
||||||
|
},
|
||||||
|
|
||||||
|
|
||||||
|
{
|
||||||
|
weekday: 1,
|
||||||
|
endHour: 17,
|
||||||
|
endMinutes: 0,
|
||||||
|
startHour: 13,
|
||||||
|
startMinutes: 0
|
||||||
|
},{
|
||||||
|
weekday: 1,
|
||||||
|
endHour: 12,
|
||||||
|
endMinutes: 0,
|
||||||
|
startHour: 10,
|
||||||
|
startMinutes: 0
|
||||||
|
},
|
||||||
|
|
||||||
|
]);
|
||||||
|
equal(rules, "Mo-Tu 10:00-12:00, 13:00-17:00;");
|
||||||
|
}],
|
||||||
|
["JOIN OH 2",() => {
|
||||||
|
const rules = OH.ToString([
|
||||||
|
|
||||||
|
{
|
||||||
|
weekday: 1,
|
||||||
|
endHour: 17,
|
||||||
|
endMinutes: 0,
|
||||||
|
startHour: 13,
|
||||||
|
startMinutes: 0
|
||||||
|
},{
|
||||||
|
weekday: 1,
|
||||||
|
endHour: 12,
|
||||||
|
endMinutes: 0,
|
||||||
|
startHour: 10,
|
||||||
|
startMinutes: 0
|
||||||
|
},
|
||||||
|
|
||||||
|
]);
|
||||||
|
equal(rules, "Tu 10:00-12:00, 13:00-17:00;");
|
||||||
|
}],
|
||||||
|
["JOIN OH 3",() => {
|
||||||
|
const rules = OH.ToString([
|
||||||
|
|
||||||
|
{
|
||||||
|
weekday: 3,
|
||||||
|
endHour: 17,
|
||||||
|
endMinutes: 0,
|
||||||
|
startHour: 13,
|
||||||
|
startMinutes: 0
|
||||||
|
},{
|
||||||
|
weekday: 1,
|
||||||
|
endHour: 12,
|
||||||
|
endMinutes: 0,
|
||||||
|
startHour: 10,
|
||||||
|
startMinutes: 0
|
||||||
|
},
|
||||||
|
|
||||||
|
]);
|
||||||
|
equal(rules, "Tu 10:00-12:00; Th 13:00-17:00;");
|
||||||
|
}],
|
||||||
|
["JOIN OH 3",() => {
|
||||||
|
const rules = OH.ToString([
|
||||||
|
|
||||||
|
{
|
||||||
|
weekday: 6,
|
||||||
|
endHour: 17,
|
||||||
|
endMinutes: 0,
|
||||||
|
startHour: 13,
|
||||||
|
startMinutes: 0
|
||||||
|
},{
|
||||||
|
weekday: 1,
|
||||||
|
endHour: 12,
|
||||||
|
endMinutes: 0,
|
||||||
|
startHour: 10,
|
||||||
|
startMinutes: 0
|
||||||
|
},
|
||||||
|
|
||||||
|
]);
|
||||||
|
equal(rules, "Tu 10:00-12:00; Sucons 13:00-17:00;");
|
||||||
|
}]
|
||||||
]);
|
]);
|
||||||
|
|
|
@ -13,7 +13,7 @@ export default class T {
|
||||||
if (failures.length == 0) {
|
if (failures.length == 0) {
|
||||||
console.log("All tests done!")
|
console.log("All tests done!")
|
||||||
} else {
|
} else {
|
||||||
console.warn(failures.length, "tests failedd :(")
|
console.warn(failures.length, "tests failed :(")
|
||||||
console.log("Failed tests: ", failures.join(","))
|
console.log("Failed tests: ", failures.join(","))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue