More work on the opening hours picker

This commit is contained in:
Pieter Vander Vennet 2020-10-06 01:37:02 +02:00
parent 4d139b45e6
commit 6563298d16
15 changed files with 321 additions and 100 deletions

View file

@ -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();

View file

@ -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)
} }
} }

View file

@ -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;
} }

View file

@ -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));

View file

@ -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> {

View file

@ -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();
}); });
} }

View file

@ -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;
} }

View file

@ -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(() => {

View file

@ -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;

View file

@ -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;

View file

@ -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 {

View file

@ -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>

21
test.ts
View file

@ -1,11 +1,24 @@
//* //*
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";

View file

@ -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;");
}]
]); ]);

View file

@ -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(","))
} }
} }