forked from MapComplete/MapComplete
		
	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,10 +207,12 @@ 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(); | ||||
|          | ||||
|         | ||||
| 
 | ||||
| 
 | ||||
|     } | ||||
| 
 | ||||
| 
 | ||||
|  |  | |||
|  | @ -8,7 +8,7 @@ export interface OpeningHour { | |||
|     endMinutes: number | ||||
| } | ||||
| 
 | ||||
| export class OpeningHourUtils { | ||||
| export class OH { | ||||
| 
 | ||||
| 
 | ||||
|     private static readonly days = ["Mo", "Tu", "We", "Th", "Fr", "Sa", "Su"] | ||||
|  | @ -23,19 +23,53 @@ export class OpeningHourUtils { | |||
|     } | ||||
| 
 | ||||
|     public static ToString(ohs: OpeningHour[]) { | ||||
|         const parts = []; | ||||
|         if (ohs.length == 0) { | ||||
|             return ""; | ||||
|         } | ||||
|         const partsPerWeekday: string [][] = [[], [], [], [], [], [], []]; | ||||
| 
 | ||||
|         function hhmm(h, m) { | ||||
|             return Utils.TwoDigits(h) + ":" + Utils.TwoDigits(m); | ||||
|         } | ||||
| 
 | ||||
|         for (const oh of ohs) { | ||||
|             parts.push( | ||||
|                 OpeningHourUtils.days[oh.weekday] + " " + hhmm(oh.startHour, oh.startMinutes) + "-" + hhmm(oh.endHour, oh.endMinutes) | ||||
|             ) | ||||
|             partsPerWeekday[oh.weekday].push(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 | ||||
|                 } | ||||
| 
 | ||||
|                 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
 | ||||
|                     doAddEntry = false; | ||||
|                     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
 | ||||
|                     newList.splice(i, 1); | ||||
|                     break; | ||||
|                 } | ||||
| 
 | ||||
|                 if (OpeningHourUtils.startTimeLiesInRange(maybeAdd, guard) || OpeningHourUtils.endTimeLiesInRange(maybeAdd, guard) | ||||
|                     || OpeningHourUtils.startTimeLiesInRange(guard, maybeAdd) || OpeningHourUtils.endTimeLiesInRange(guard, maybeAdd)) { | ||||
|                 if (OH.startTimeLiesInRange(maybeAdd, guard) || OH.endTimeLiesInRange(maybeAdd, guard) | ||||
|                     || OH.startTimeLiesInRange(guard, maybeAdd) || OH.endTimeLiesInRange(guard, maybeAdd)) { | ||||
|                     // At this point, the maybeAdd overlaps the guard: we should extend the guard and retest it
 | ||||
|                     newList.splice(i, 1); | ||||
|                     let startHour = guard.startHour; | ||||
|                     let startMinutes = guard.startMinutes; | ||||
|                     if(OpeningHourUtils.startTime(maybeAdd)<OpeningHourUtils.startTime(guard)){ | ||||
|                     if (OH.startTime(maybeAdd) < OH.startTime(guard)) { | ||||
|                         startHour = maybeAdd.startHour; | ||||
|                         startMinutes = maybeAdd.startMinutes; | ||||
|                     } | ||||
| 
 | ||||
|                     let endHour = guard.endHour; | ||||
|                     let endMinutes = guard.endMinutes; | ||||
|                     if(OpeningHourUtils.endTime(maybeAdd)>OpeningHourUtils.endTime(guard)){ | ||||
|                     if (OH.endTime(maybeAdd) > OH.endTime(guard)) { | ||||
|                         endHour = maybeAdd.endHour; | ||||
|                         endMinutes = maybeAdd.endMinutes; | ||||
|                     } | ||||
|  | @ -130,51 +164,128 @@ export class OpeningHourUtils { | |||
|     } | ||||
| 
 | ||||
|     public static startTimeLiesInRange(checked: OpeningHour, mightLieIn: OpeningHour) { | ||||
|         return OpeningHourUtils.startTime(mightLieIn) <= OpeningHourUtils.startTime(checked) && | ||||
|             OpeningHourUtils.startTime(checked) <= OpeningHourUtils.endTime(mightLieIn) | ||||
|         return OH.startTime(mightLieIn) <= OH.startTime(checked) && | ||||
|             OH.startTime(checked) <= OH.endTime(mightLieIn) | ||||
|     } | ||||
| 
 | ||||
|     public static endTimeLiesInRange(checked: OpeningHour, mightLieIn: OpeningHour) { | ||||
|         return OpeningHourUtils.startTime(mightLieIn) <= OpeningHourUtils.endTime(checked) && | ||||
|             OpeningHourUtils.endTime(checked) <= OpeningHourUtils.endTime(mightLieIn) | ||||
|         return OH.startTime(mightLieIn) <= OH.endTime(checked) && | ||||
|             OH.endTime(checked) <= OH.endTime(mightLieIn) | ||||
|     } | ||||
| 
 | ||||
|     static Parse(str: string) { | ||||
|         if (str === undefined || str === "") { | ||||
|     private static parseHHMM(hhmm: string): { hours: number, minutes: number } { | ||||
|         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 [] | ||||
|         } | ||||
| 
 | ||||
|         const parts = str.toLowerCase().split(";"); | ||||
|         const ohs = [] | ||||
| 
 | ||||
|         function parseTime(hhmm) { | ||||
|             const spl = hhmm.trim().split(":"); | ||||
|             return [Number(spl[0].trim()), Number(spl[1].trim())] | ||||
|         } | ||||
|         const split = rules.split(";"); | ||||
| 
 | ||||
|         for (const part of parts) { | ||||
|             if(part === ""){ | ||||
|         for (const rule of split) { | ||||
|             if(rule === ""){ | ||||
|                 continue; | ||||
|             } | ||||
|             try { | ||||
| 
 | ||||
|                 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); | ||||
| 
 | ||||
|                 ohs.push(...OH.ParseRule(rule)); | ||||
|             } 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> { | ||||
|         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); | ||||
|         return this; | ||||
|     } | ||||
|  |  | |||
							
								
								
									
										5
									
								
								State.ts
									
										
									
									
									
								
							
							
						
						
									
										5
									
								
								State.ts
									
										
									
									
									
								
							|  | @ -111,9 +111,9 @@ export default class State { | |||
|      * The location as delivered by the GPS | ||||
|      */ | ||||
|     public currentGPSLocation: UIEventSource<{ | ||||
|         latlng: number, | ||||
|         latlng: {lat:number, lon:number}, | ||||
|         accuracy: number | ||||
|     }> = new UIEventSource<{ latlng: number, accuracy: number }>(undefined); | ||||
|     }> = new UIEventSource<{ latlng: {lat:number, lon:number}, accuracy: number }>(undefined); | ||||
|     public layoutDefinition: string; | ||||
|     public installedThemes: UIEventSource<{ layout: Layout; definition: string }[]>; | ||||
| 
 | ||||
|  | @ -139,7 +139,6 @@ export default class State { | |||
|                 return ("" + fl).substr(0, 8); | ||||
|             }) | ||||
|         } | ||||
| 
 | ||||
|         this.zoom = asFloat( | ||||
|             QueryParameters.GetQueryParameter("z", "" + layoutToUse.startzoom) | ||||
|             .syncWith(LocalStorageSource.Get("zoom"), true)); | ||||
|  |  | |||
|  | @ -35,8 +35,6 @@ export default class InputElementMap<T, X> extends InputElement<X> { | |||
|             }), extraSources, x => { | ||||
|                 return fromX(x); | ||||
|             }); | ||||
|         this._value.addCallback(console.log) | ||||
|         this.IsSelected.addCallback(s => console.log("Is selected?", s)) | ||||
|     } | ||||
| 
 | ||||
|     GetValue(): UIEventSource<X> { | ||||
|  |  | |||
|  | @ -1,6 +1,6 @@ | |||
| import {UIElement} from "../../UIElement"; | ||||
| import {InputElement} from "../InputElement"; | ||||
| import {OpeningHour, OpeningHourUtils} from "../../../Logic/OpeningHours"; | ||||
| import {OpeningHour, OH} from "../../../Logic/OpeningHours"; | ||||
| import {UIEventSource} from "../../../Logic/UIEventSource"; | ||||
| import OpeningHoursPickerTable from "./OpeningHoursPickerTable"; | ||||
| import OpeningHoursRange from "./OpeningHoursRange"; | ||||
|  | @ -17,23 +17,16 @@ export default class OpeningHoursPicker extends InputElement<OpeningHour[]> { | |||
|     constructor(ohs: UIEventSource<OpeningHour[]> = new UIEventSource<OpeningHour[]>([])) { | ||||
|         super(); | ||||
|         this._ohs = ohs; | ||||
|         this._backgroundTable = new OpeningHoursPickerTable(this._weekdays); | ||||
|         this._backgroundTable = new OpeningHoursPickerTable(this._weekdays, this._ohs); | ||||
|         const self = this; | ||||
|          | ||||
|         this._backgroundTable.GetValue().addCallback(oh => { | ||||
|             if (oh) { | ||||
|                 ohs.data.push(oh); | ||||
|                 ohs.ping(); | ||||
|             } | ||||
|         }); | ||||
|          | ||||
|         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[][] = []; | ||||
| 
 | ||||
|             for (let i = 0; i < 7; i++) { | ||||
|                 perWeekday[i] = []; | ||||
|             } | ||||
|  | @ -41,7 +34,7 @@ export default class OpeningHoursPicker extends InputElement<OpeningHour[]> { | |||
|             for (const oh of ohs) { | ||||
|                 const source = new UIEventSource<OpeningHour>(oh) | ||||
|                 source.addCallback(_ => { | ||||
|                     self._ohs.setData(OpeningHourUtils.MergeTimes(self._ohs.data)) | ||||
|                     self._ohs.setData(OH.MergeTimes(self._ohs.data)) | ||||
|                 }) | ||||
|                 const r = new OpeningHoursRange(source); | ||||
|                 perWeekday[oh.weekday].push(r); | ||||
|  | @ -52,7 +45,6 @@ export default class OpeningHoursPicker extends InputElement<OpeningHour[]> { | |||
|             } | ||||
|             self._weekdays.ping(); | ||||
| 
 | ||||
| 
 | ||||
|         }); | ||||
| 
 | ||||
|     } | ||||
|  |  | |||
|  | @ -8,19 +8,19 @@ import {UIElement} from "../../UIElement"; | |||
|  * 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> { | ||||
| export default class OpeningHoursPickerTable extends InputElement<OpeningHour[]> { | ||||
|     public readonly IsSelected: UIEventSource<boolean>; | ||||
|     private readonly weekdays: UIEventSource<UIElement[]>; | ||||
| 
 | ||||
|     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); | ||||
|         this.weekdays = weekdays; | ||||
|         this.source = source ?? new UIEventSource<OpeningHour>(undefined); | ||||
|         this.source = source ?? new UIEventSource<OpeningHour[]>([]); | ||||
|         this.IsSelected = new UIEventSource<boolean>(false); | ||||
|         this.SetStyle("width:100%;height:100%;display:block;"); | ||||
| 
 | ||||
|  | @ -105,8 +105,9 @@ export default class OpeningHoursPickerTable extends InputElement<OpeningHour> { | |||
|                     oh.endHour = 24; | ||||
|                     oh.endMinutes = 0; | ||||
|                 } | ||||
|                 self.source.setData(oh); | ||||
|                 self.source.data.push(oh); | ||||
|             } | ||||
|             self.source.ping(); | ||||
| 
 | ||||
|             // Clear the highlighting
 | ||||
|             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; | ||||
|     } | ||||
| 
 | ||||
|     GetValue(): UIEventSource<OpeningHour> { | ||||
|     GetValue(): UIEventSource<OpeningHour[]> { | ||||
|         return this.source; | ||||
|     } | ||||
| 
 | ||||
|  |  | |||
|  | @ -26,7 +26,6 @@ export default class OpeningHoursRange extends UIElement { | |||
|             self.InnerUpdate(el); | ||||
|         }) | ||||
| 
 | ||||
| 
 | ||||
|         this._deleteRange = new FixedUiElement("<img src='./assets/delete.svg'>") | ||||
|             .SetClass("oh-delete-range") | ||||
|             .onClick(() => { | ||||
|  |  | |||
|  | @ -9,7 +9,7 @@ import {UIEventSource} from "../../Logic/UIEventSource"; | |||
| import CombinedInputElement from "./CombinedInputElement"; | ||||
| import SimpleDatePicker from "./SimpleDatePicker"; | ||||
| import OpeningHoursPicker from "./OpeningHours/OpeningHoursPicker"; | ||||
| import {OpeningHour, OpeningHourUtils} from "../../Logic/OpeningHours"; | ||||
| import {OpeningHour, OH} from "../../Logic/OpeningHours"; | ||||
| 
 | ||||
| interface TextFieldDef { | ||||
|     name: string, | ||||
|  | @ -148,15 +148,17 @@ export default class ValidatedTextField { | |||
|             "opening_hours", | ||||
|             "Has extra elements to easily input when a POI is opened", | ||||
|             (s, country) => true, // TODO
 | ||||
|             str => str, // TODO reformat with opening_hours.js
 | ||||
|             str => str,  | ||||
|             (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, | ||||
|                     ohs => OpeningHourUtils.ToString(ohs), | ||||
|                     str => OpeningHourUtils.Parse(str) | ||||
|                     ohs =>  OH.ToString(ohs), | ||||
|                     str => OH.Parse(str) | ||||
|                 ) | ||||
|                 input.GetValue().addCallback(latest => { | ||||
|                     console.log(latest); | ||||
|                     value.setData(latest); | ||||
|                 }) | ||||
|                 return input; | ||||
|  |  | |||
|  | @ -71,8 +71,8 @@ export class TagRendering extends UIElement implements TagDependantUIElement { | |||
|     }) { | ||||
|         super(tags); | ||||
|         this.ListenTo(Locale.language); | ||||
|         this.ListenTo(this._questionSkipped); | ||||
|         this.ListenTo(this._editMode); | ||||
|         this.ListenTo(this._questionSkipped); | ||||
|         this.ListenTo(State.state?.osmConnection?.userDetails); | ||||
| 
 | ||||
|         const self = this; | ||||
|  |  | |||
|  | @ -17,13 +17,6 @@ body { | |||
|     position: absolute; | ||||
|     bottom: 25px; | ||||
|     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 { | ||||
|  |  | |||
|  | @ -58,7 +58,7 @@ | |||
| <div id="centermessage">Loading MapComplete, hang on...</div> | ||||
| <div id="top-right"></div> | ||||
| 
 | ||||
| <div id="geolocate-button"></div> | ||||
| <span id="geolocate-button"></span> | ||||
| <div id="leafletDiv"></div> | ||||
| 
 | ||||
| <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 {FixedUiElement} from "./UI/Base/FixedUiElement"; | ||||
| 
 | ||||
| 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"; | ||||
| 
 | ||||
| UIElement.runningFromConsole = true; | ||||
| 
 | ||||
| import {equal} from "assert"; | ||||
| import Translation from "../UI/i18n/Translation"; | ||||
| import T from "./TestHelper"; | ||||
|  | @ -9,11 +7,10 @@ import {FromJSON} from "../Customizations/JSON/FromJSON"; | |||
| import {And, Tag} from "../Logic/Tags"; | ||||
| import Locale from "../UI/i18n/Locale"; | ||||
| import Translations from "../UI/i18n/Translations"; | ||||
| import {TagRenderingOptions} from "../Customizations/TagRenderingOptions"; | ||||
| import {UIEventSource} from "../Logic/UIEventSource"; | ||||
| import {TagRendering} from "../UI/TagRendering"; | ||||
| import {Basemap} from "../Logic/Leaflet/Basemap"; | ||||
| import {OpeningHour, OpeningHourUtils} from "../Logic/OpeningHours"; | ||||
| import {OH, OpeningHour} from "../Logic/OpeningHours"; | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| new T([ | ||||
|  | @ -140,7 +137,7 @@ new T([ | |||
|                 endMinutes: 0 | ||||
|             }; | ||||
|              | ||||
|             const merged = OpeningHourUtils.MergeTimes([oh0, oh1]); | ||||
|             const merged = OH.MergeTimes([oh0, oh1]); | ||||
|             const r = merged[0]; | ||||
|             equal( merged.length, 1); | ||||
|             equal(r.startHour,10 ); | ||||
|  | @ -165,12 +162,122 @@ new T([ | |||
|                 endMinutes: 0 | ||||
|             }; | ||||
| 
 | ||||
|             const merged = OpeningHourUtils.MergeTimes([oh0, oh1]); | ||||
|             const merged = OH.MergeTimes([oh0, oh1]); | ||||
|             const r = merged[0]; | ||||
|             equal( merged.length, 1); | ||||
|             equal(r.startHour,10 ); | ||||
|             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) { | ||||
|             console.log("All tests done!") | ||||
|         } else { | ||||
|             console.warn(failures.length, "tests failedd :(") | ||||
|             console.warn(failures.length, "tests failed :(") | ||||
|             console.log("Failed tests: ", failures.join(",")) | ||||
|         } | ||||
|     } | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue