forked from MapComplete/MapComplete
		
	Last fixes to the OH picker
This commit is contained in:
		
							parent
							
								
									64ec06bfc8
								
							
						
					
					
						commit
						48f66bd17e
					
				
					 11 changed files with 327 additions and 311 deletions
				
			
		| 
						 | 
					@ -210,6 +210,7 @@ export class InitUiElements {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // Reset the loading message once things are loaded
 | 
					        // Reset the loading message once things are loaded
 | 
				
			||||||
        new CenterMessageBox().AttachTo("centermessage");
 | 
					        new CenterMessageBox().AttachTo("centermessage");
 | 
				
			||||||
 | 
					        document.getElementById("centermessage").classList.add("pointer-events-none")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -49,10 +49,10 @@ export class OH {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        let rangeStart = 0;
 | 
					        let rangeStart = 0;
 | 
				
			||||||
        let rangeEnd = 0;
 | 
					        let rangeEnd = 0;
 | 
				
			||||||
        
 | 
					
 | 
				
			||||||
        function pushRule(){
 | 
					        function pushRule() {
 | 
				
			||||||
            const rule = stringPerWeekday[rangeStart];
 | 
					            const rule = stringPerWeekday[rangeStart];
 | 
				
			||||||
            if(rule === ""){
 | 
					            if (rule === "") {
 | 
				
			||||||
                return;
 | 
					                return;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            if (rangeStart == (rangeEnd - 1)) {
 | 
					            if (rangeStart == (rangeEnd - 1)) {
 | 
				
			||||||
| 
						 | 
					@ -61,7 +61,7 @@ export class OH {
 | 
				
			||||||
                );
 | 
					                );
 | 
				
			||||||
            } else {
 | 
					            } else {
 | 
				
			||||||
                rules.push(
 | 
					                rules.push(
 | 
				
			||||||
                    `${OH.days[rangeStart]}-${OH.days[rangeEnd-1]} ${rule}`
 | 
					                    `${OH.days[rangeStart]}-${OH.days[rangeEnd - 1]} ${rule}`
 | 
				
			||||||
                );
 | 
					                );
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
| 
						 | 
					@ -90,13 +90,22 @@ export class OH {
 | 
				
			||||||
     * @constructor
 | 
					     * @constructor
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    public static MergeTimes(ohs: OpeningHour[]): OpeningHour[] {
 | 
					    public static MergeTimes(ohs: OpeningHour[]): OpeningHour[] {
 | 
				
			||||||
        const queue = [...ohs];
 | 
					        const queue = ohs.map(oh => {
 | 
				
			||||||
 | 
					            if (oh.endHour === 0 && oh.endMinutes === 0) {
 | 
				
			||||||
 | 
					                const newOh = {
 | 
				
			||||||
 | 
					                        ...oh
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					                newOh.endHour = 24
 | 
				
			||||||
 | 
					                return newOh
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            return oh;
 | 
				
			||||||
 | 
					        });
 | 
				
			||||||
        const newList = [];
 | 
					        const newList = [];
 | 
				
			||||||
        while (queue.length > 0) {
 | 
					        while (queue.length > 0) {
 | 
				
			||||||
            let maybeAdd = queue.pop();
 | 
					            let maybeAdd = queue.pop();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            let doAddEntry = true;
 | 
					            let doAddEntry = true;
 | 
				
			||||||
            if(maybeAdd.weekday == undefined){
 | 
					            if (maybeAdd.weekday == undefined) {
 | 
				
			||||||
                doAddEntry = false;
 | 
					                doAddEntry = false;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -140,8 +149,8 @@ export class OH {
 | 
				
			||||||
                    queue.push({
 | 
					                    queue.push({
 | 
				
			||||||
                        startHour: startHour,
 | 
					                        startHour: startHour,
 | 
				
			||||||
                        startMinutes: startMinutes,
 | 
					                        startMinutes: startMinutes,
 | 
				
			||||||
                        endHour:endHour,
 | 
					                        endHour: endHour,
 | 
				
			||||||
                        endMinutes:endMinutes,
 | 
					                        endMinutes: endMinutes,
 | 
				
			||||||
                        weekday: guard.weekday
 | 
					                        weekday: guard.weekday
 | 
				
			||||||
                    });
 | 
					                    });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -190,21 +199,6 @@ export class OH {
 | 
				
			||||||
            OH.endTime(checked) <= OH.endTime(mightLieIn)
 | 
					            OH.endTime(checked) <= OH.endTime(mightLieIn)
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    private static parseHHMM(hhmm: string): { hours: number, minutes: number } {
 | 
					 | 
				
			||||||
        if(hhmm === undefined || hhmm == null){
 | 
					 | 
				
			||||||
            return null;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        const spl = hhmm.trim().split(":");
 | 
					 | 
				
			||||||
        if(spl.length != 2){
 | 
					 | 
				
			||||||
            return null;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        const hm = {hours: Number(spl[0].trim()), minutes: Number(spl[1].trim())};
 | 
					 | 
				
			||||||
        if(isNaN(hm.hours) || isNaN(hm.minutes) ){
 | 
					 | 
				
			||||||
            return null;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        return hm;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    public static parseHHMMRange(hhmmhhmm: string): {
 | 
					    public static parseHHMMRange(hhmmhhmm: string): {
 | 
				
			||||||
        startHour: number,
 | 
					        startHour: number,
 | 
				
			||||||
        startMinutes: number,
 | 
					        startMinutes: number,
 | 
				
			||||||
| 
						 | 
					@ -226,80 +220,6 @@ export class OH {
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    private static ParseHhmmRanges(hhmms: string): {
 | 
					 | 
				
			||||||
        startHour: number,
 | 
					 | 
				
			||||||
        startMinutes: number,
 | 
					 | 
				
			||||||
        endHour: number,
 | 
					 | 
				
			||||||
        endMinutes: number
 | 
					 | 
				
			||||||
    }[] {
 | 
					 | 
				
			||||||
        if (hhmms === "off") {
 | 
					 | 
				
			||||||
            return [];
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        return hhmms.split(",")
 | 
					 | 
				
			||||||
            .map(s => s.trim())
 | 
					 | 
				
			||||||
            .filter(str => str !== "")
 | 
					 | 
				
			||||||
            .map(OH.parseHHMMRange)
 | 
					 | 
				
			||||||
            .filter(v => v != null)
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    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) {
 | 
					 | 
				
			||||||
            const parsed = OH.ParseWeekday(weekdays);
 | 
					 | 
				
			||||||
            if(parsed == null){
 | 
					 | 
				
			||||||
                return null;
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
            return [parsed];
 | 
					 | 
				
			||||||
        } else if (split.length == 2) {
 | 
					 | 
				
			||||||
            let start = OH.ParseWeekday(split[0]);
 | 
					 | 
				
			||||||
            let end = OH.ParseWeekday(split[1]);
 | 
					 | 
				
			||||||
            if ((start ?? null) === null || (end ?? null) === null) {
 | 
					 | 
				
			||||||
                return null;
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
            let range = [];
 | 
					 | 
				
			||||||
            for (let i = start; i <= end; i++) {
 | 
					 | 
				
			||||||
                range.push(i);
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
            return range;
 | 
					 | 
				
			||||||
        } else {
 | 
					 | 
				
			||||||
            return null;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    private static ParseWeekdayRanges(weekdays: string): number[] {
 | 
					 | 
				
			||||||
        let ranges = [];
 | 
					 | 
				
			||||||
        let split = weekdays.split(",");
 | 
					 | 
				
			||||||
        for (const weekday of split) {
 | 
					 | 
				
			||||||
            const parsed = OH.ParseWeekdayRange(weekday)
 | 
					 | 
				
			||||||
            if (parsed === undefined || parsed === null) {
 | 
					 | 
				
			||||||
                return null;
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
            ranges.push(...parsed);
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        return ranges;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    private static multiply(weekdays: number[], timeranges: { startHour: number, startMinutes: number, endHour: number, endMinutes: number }[]) {
 | 
					 | 
				
			||||||
        if ((weekdays ?? null) == null || (timeranges ?? null) == null) {
 | 
					 | 
				
			||||||
            return null;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        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[] {
 | 
					    public static ParseRule(rule: string): OpeningHour[] {
 | 
				
			||||||
        try {
 | 
					        try {
 | 
				
			||||||
            if (rule.trim() == "24/7") {
 | 
					            if (rule.trim() == "24/7") {
 | 
				
			||||||
| 
						 | 
					@ -331,6 +251,49 @@ export class OH {
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public static ParsePHRule(str: string): {
 | 
				
			||||||
 | 
					        mode: string,
 | 
				
			||||||
 | 
					        start?: string,
 | 
				
			||||||
 | 
					        end?: string
 | 
				
			||||||
 | 
					    } {
 | 
				
			||||||
 | 
					        str = str.trim();
 | 
				
			||||||
 | 
					        if (!str.startsWith("PH")) {
 | 
				
			||||||
 | 
					            return null;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        str = str.trim();
 | 
				
			||||||
 | 
					        if (str === "PH off") {
 | 
				
			||||||
 | 
					            return {
 | 
				
			||||||
 | 
					                mode: "off"
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (str === "PH open") {
 | 
				
			||||||
 | 
					            return {
 | 
				
			||||||
 | 
					                mode: "open"
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (!str.startsWith("PH ")) {
 | 
				
			||||||
 | 
					            return null;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        try {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            const timerange = OH.parseHHMMRange(str.substring(2));
 | 
				
			||||||
 | 
					            if (timerange === null) {
 | 
				
			||||||
 | 
					                return null;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            return {
 | 
				
			||||||
 | 
					                mode: " ",
 | 
				
			||||||
 | 
					                start: OH.hhmm(timerange.startHour, timerange.startMinutes),
 | 
				
			||||||
 | 
					                end: OH.hhmm(timerange.endHour, timerange.endMinutes),
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        } catch (e) {
 | 
				
			||||||
 | 
					            return null;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    static Parse(rules: string) {
 | 
					    static Parse(rules: string) {
 | 
				
			||||||
        if (rules === undefined || rules === "") {
 | 
					        if (rules === undefined || rules === "") {
 | 
				
			||||||
| 
						 | 
					@ -342,7 +305,7 @@ export class OH {
 | 
				
			||||||
        const split = rules.split(";");
 | 
					        const split = rules.split(";");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        for (const rule of split) {
 | 
					        for (const rule of split) {
 | 
				
			||||||
            if(rule === ""){
 | 
					            if (rule === "") {
 | 
				
			||||||
                continue;
 | 
					                continue;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            try {
 | 
					            try {
 | 
				
			||||||
| 
						 | 
					@ -376,7 +339,7 @@ export class OH {
 | 
				
			||||||
    }[][]): [number[], string[]] {
 | 
					    }[][]): [number[], string[]] {
 | 
				
			||||||
        const changeHours: number[] = []
 | 
					        const changeHours: number[] = []
 | 
				
			||||||
        const changeHourText: string[] = [];
 | 
					        const changeHourText: string[] = [];
 | 
				
			||||||
        
 | 
					
 | 
				
			||||||
        const extrachangeHours: number[] = []
 | 
					        const extrachangeHours: number[] = []
 | 
				
			||||||
        const extrachangeHourText: string[] = [];
 | 
					        const extrachangeHourText: string[] = [];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -387,7 +350,7 @@ export class OH {
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
                const startOfDay: Date = new Date(range.startDate);
 | 
					                const startOfDay: Date = new Date(range.startDate);
 | 
				
			||||||
                startOfDay.setHours(0, 0, 0, 0);
 | 
					                startOfDay.setHours(0, 0, 0, 0);
 | 
				
			||||||
                
 | 
					
 | 
				
			||||||
                // The number of seconds since the start of the day
 | 
					                // The number of seconds since the start of the day
 | 
				
			||||||
                // @ts-ignore
 | 
					                // @ts-ignore
 | 
				
			||||||
                const changeMoment: number = (range.startDate - startOfDay) / 1000;
 | 
					                const changeMoment: number = (range.startDate - startOfDay) / 1000;
 | 
				
			||||||
| 
						 | 
					@ -417,7 +380,7 @@ export class OH {
 | 
				
			||||||
        changeHours.sort();
 | 
					        changeHours.sort();
 | 
				
			||||||
        extrachangeHourText.sort();
 | 
					        extrachangeHourText.sort();
 | 
				
			||||||
        extrachangeHours.sort();
 | 
					        extrachangeHours.sort();
 | 
				
			||||||
        
 | 
					
 | 
				
			||||||
        changeHourText.push(...extrachangeHourText);
 | 
					        changeHourText.push(...extrachangeHourText);
 | 
				
			||||||
        changeHours.push(...extrachangeHours);
 | 
					        changeHours.push(...extrachangeHours);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -476,6 +439,95 @@ export class OH {
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        return values;
 | 
					        return values;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    
 | 
					
 | 
				
			||||||
 | 
					    private static parseHHMM(hhmm: string): { hours: number, minutes: number } {
 | 
				
			||||||
 | 
					        if (hhmm === undefined || hhmm == null) {
 | 
				
			||||||
 | 
					            return null;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        const spl = hhmm.trim().split(":");
 | 
				
			||||||
 | 
					        if (spl.length != 2) {
 | 
				
			||||||
 | 
					            return null;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        const hm = {hours: Number(spl[0].trim()), minutes: Number(spl[1].trim())};
 | 
				
			||||||
 | 
					        if (isNaN(hm.hours) || isNaN(hm.minutes)) {
 | 
				
			||||||
 | 
					            return null;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        return hm;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private static ParseHhmmRanges(hhmms: string): {
 | 
				
			||||||
 | 
					        startHour: number,
 | 
				
			||||||
 | 
					        startMinutes: number,
 | 
				
			||||||
 | 
					        endHour: number,
 | 
				
			||||||
 | 
					        endMinutes: number
 | 
				
			||||||
 | 
					    }[] {
 | 
				
			||||||
 | 
					        if (hhmms === "off") {
 | 
				
			||||||
 | 
					            return [];
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        return hhmms.split(",")
 | 
				
			||||||
 | 
					            .map(s => s.trim())
 | 
				
			||||||
 | 
					            .filter(str => str !== "")
 | 
				
			||||||
 | 
					            .map(OH.parseHHMMRange)
 | 
				
			||||||
 | 
					            .filter(v => v != null)
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    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) {
 | 
				
			||||||
 | 
					            const parsed = OH.ParseWeekday(weekdays);
 | 
				
			||||||
 | 
					            if (parsed == null) {
 | 
				
			||||||
 | 
					                return null;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            return [parsed];
 | 
				
			||||||
 | 
					        } else if (split.length == 2) {
 | 
				
			||||||
 | 
					            let start = OH.ParseWeekday(split[0]);
 | 
				
			||||||
 | 
					            let end = OH.ParseWeekday(split[1]);
 | 
				
			||||||
 | 
					            if ((start ?? null) === null || (end ?? null) === null) {
 | 
				
			||||||
 | 
					                return null;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            let range = [];
 | 
				
			||||||
 | 
					            for (let i = start; i <= end; i++) {
 | 
				
			||||||
 | 
					                range.push(i);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            return range;
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					            return null;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private static ParseWeekdayRanges(weekdays: string): number[] {
 | 
				
			||||||
 | 
					        let ranges = [];
 | 
				
			||||||
 | 
					        let split = weekdays.split(",");
 | 
				
			||||||
 | 
					        for (const weekday of split) {
 | 
				
			||||||
 | 
					            const parsed = OH.ParseWeekdayRange(weekday)
 | 
				
			||||||
 | 
					            if (parsed === undefined || parsed === null) {
 | 
				
			||||||
 | 
					                return null;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            ranges.push(...parsed);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        return ranges;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private static multiply(weekdays: number[], timeranges: { startHour: number, startMinutes: number, endHour: number, endMinutes: number }[]) {
 | 
				
			||||||
 | 
					        if ((weekdays ?? null) == null || (timeranges ?? null) == null) {
 | 
				
			||||||
 | 
					            return null;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        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;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -37,14 +37,14 @@ export default class OpeningHoursInput extends InputElement<string> {
 | 
				
			||||||
                if (OH.ParseRule(rule) !== null) {
 | 
					                if (OH.ParseRule(rule) !== null) {
 | 
				
			||||||
                    continue;
 | 
					                    continue;
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
                if (PublicHolidayInput.LoadValue(rule) !== null) {
 | 
					                if (OH.ParsePHRule(rule) !== null) {
 | 
				
			||||||
                    continue;
 | 
					                    continue;
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
                leftOvers.push(rule);
 | 
					                leftOvers.push(rule);
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            return leftOvers;
 | 
					            return leftOvers;
 | 
				
			||||||
        })
 | 
					        })
 | 
				
			||||||
        // NOte: MUST be bound AFTER the leftover rules!
 | 
					        // Note: MUST be bound AFTER the leftover rules!
 | 
				
			||||||
        const rulesFromOhPicker = value.map(OH.Parse);
 | 
					        const rulesFromOhPicker = value.map(OH.Parse);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        const ph = value.map<string>(str => {
 | 
					        const ph = value.map<string>(str => {
 | 
				
			||||||
| 
						 | 
					@ -53,7 +53,7 @@ export default class OpeningHoursInput extends InputElement<string> {
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            const rules = str.split(";");
 | 
					            const rules = str.split(";");
 | 
				
			||||||
            for (const rule of rules) {
 | 
					            for (const rule of rules) {
 | 
				
			||||||
                if (PublicHolidayInput.LoadValue(rule) !== null) {
 | 
					                if (OH.ParsePHRule(rule) !== null) {
 | 
				
			||||||
                    return rule;
 | 
					                    return rule;
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,6 +1,4 @@
 | 
				
			||||||
import {UIEventSource} from "../../Logic/UIEventSource";
 | 
					import {UIEventSource} from "../../Logic/UIEventSource";
 | 
				
			||||||
import OpeningHoursRange from "./OpeningHoursRange";
 | 
					 | 
				
			||||||
import Combine from "../Base/Combine";
 | 
					 | 
				
			||||||
import OpeningHoursPickerTable from "./OpeningHoursPickerTable";
 | 
					import OpeningHoursPickerTable from "./OpeningHoursPickerTable";
 | 
				
			||||||
import {OH, OpeningHour} from "./OpeningHours";
 | 
					import {OH, OpeningHour} from "./OpeningHours";
 | 
				
			||||||
import {InputElement} from "../Input/InputElement";
 | 
					import {InputElement} from "../Input/InputElement";
 | 
				
			||||||
| 
						 | 
					@ -22,8 +20,6 @@ export default class OpeningHoursPicker extends InputElement<OpeningHour[]> {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        this._backgroundTable = new OpeningHoursPickerTable(this._ohs);
 | 
					        this._backgroundTable = new OpeningHoursPickerTable(this._ohs);
 | 
				
			||||||
        this._backgroundTable.ConstructElement()
 | 
					        this._backgroundTable.ConstructElement()
 | 
				
			||||||
 | 
					 | 
				
			||||||
        ohs.ping();
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    InnerRender(): BaseUIElement {
 | 
					    InnerRender(): BaseUIElement {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -51,17 +51,23 @@ export default class OpeningHoursPickerTable extends InputElement<OpeningHour[]>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        const table = document.createElement("table")
 | 
					        const table = document.createElement("table")
 | 
				
			||||||
        table.classList.add("oh-table")
 | 
					        table.classList.add("oh-table")
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        const cellHeightInPx = 14;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        const headerRow = document.createElement("tr")
 | 
					        const headerRow = document.createElement("tr")
 | 
				
			||||||
        headerRow.appendChild(document.createElement("th"))
 | 
					        headerRow.appendChild(document.createElement("th"))
 | 
				
			||||||
 | 
					        headerRow.classList.add("relative")
 | 
				
			||||||
        for (let i = 0; i < OpeningHoursPickerTable.days.length; i++) {
 | 
					        for (let i = 0; i < OpeningHoursPickerTable.days.length; i++) {
 | 
				
			||||||
            let weekday = OpeningHoursPickerTable.days[i].Clone();
 | 
					            let weekday = OpeningHoursPickerTable.days[i].Clone();
 | 
				
			||||||
            const cell = document.createElement("th")
 | 
					            const cell = document.createElement("th")
 | 
				
			||||||
            cell.style.width = "14%"
 | 
					            cell.style.width = "14%"
 | 
				
			||||||
            cell.appendChild(weekday.ConstructElement())
 | 
					            cell.appendChild(weekday.ConstructElement())
 | 
				
			||||||
 | 
					            
 | 
				
			||||||
            const fullColumnSpan = this.weekdayElements[i]
 | 
					            const fullColumnSpan = this.weekdayElements[i]
 | 
				
			||||||
            fullColumnSpan.classList.add("w-full","h-full","relative")
 | 
					            fullColumnSpan.classList.add("w-full","relative")
 | 
				
			||||||
            fullColumnSpan.style.height = "42rem"  
 | 
					            
 | 
				
			||||||
 | 
					            // 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(
 | 
					            const ranges = new VariableUiElement(
 | 
				
			||||||
| 
						 | 
					@ -98,7 +104,7 @@ export default class OpeningHoursPickerTable extends InputElement<OpeningHour[]>
 | 
				
			||||||
            const hs = Utils.TwoDigits(h);
 | 
					            const hs = Utils.TwoDigits(h);
 | 
				
			||||||
            const firstCell = document.createElement("td")
 | 
					            const firstCell = document.createElement("td")
 | 
				
			||||||
            firstCell.rowSpan = 2
 | 
					            firstCell.rowSpan = 2
 | 
				
			||||||
            firstCell.classList.add("oh-left-col", "oh-timecell-full", "border-box","h-2")
 | 
					            firstCell.classList.add("oh-left-col", "oh-timecell-full", "border-box")
 | 
				
			||||||
            firstCell.appendChild(new FixedUiElement(hs + ":00").ConstructElement())
 | 
					            firstCell.appendChild(new FixedUiElement(hs + ":00").ConstructElement())
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            const evenRow = document.createElement("tr")
 | 
					            const evenRow = document.createElement("tr")
 | 
				
			||||||
| 
						 | 
					@ -109,6 +115,9 @@ export default class OpeningHoursPickerTable extends InputElement<OpeningHour[]>
 | 
				
			||||||
                cell.classList.add("oh-timecell", "oh-timecell-full", `oh-timecell-${weekday}`)
 | 
					                cell.classList.add("oh-timecell", "oh-timecell-full", `oh-timecell-${weekday}`)
 | 
				
			||||||
                evenRow.appendChild(cell)
 | 
					                evenRow.appendChild(cell)
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					            evenRow.style.height = (cellHeightInPx)+"px";
 | 
				
			||||||
 | 
					            evenRow.style.maxHeight = evenRow.style.height;
 | 
				
			||||||
 | 
					            evenRow.style.minHeight = evenRow.style.height;
 | 
				
			||||||
            table.appendChild(evenRow)
 | 
					            table.appendChild(evenRow)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            const oddRow = document.createElement("tr")
 | 
					            const oddRow = document.createElement("tr")
 | 
				
			||||||
| 
						 | 
					@ -118,6 +127,9 @@ export default class OpeningHoursPickerTable extends InputElement<OpeningHour[]>
 | 
				
			||||||
                cell.classList.add("oh-timecell", "oh-timecell-half", `oh-timecell-${weekday}`)
 | 
					                cell.classList.add("oh-timecell", "oh-timecell-half", `oh-timecell-${weekday}`)
 | 
				
			||||||
                oddRow.appendChild(cell)
 | 
					                oddRow.appendChild(cell)
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					            oddRow.style.minHeight = evenRow.style.height;
 | 
				
			||||||
 | 
					            oddRow.style.maxHeight = evenRow.style.height;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            table.appendChild(oddRow)
 | 
					            table.appendChild(oddRow)
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -24,28 +24,28 @@ export default class OpeningHoursRange extends BaseUIElement {
 | 
				
			||||||
    InnerConstructElement(): HTMLElement {
 | 
					    InnerConstructElement(): HTMLElement {
 | 
				
			||||||
        const height = this.getHeight();
 | 
					        const height = this.getHeight();
 | 
				
			||||||
        const oh = this._oh;
 | 
					        const oh = this._oh;
 | 
				
			||||||
        const startTime = new FixedUiElement(Utils.TwoDigits(oh.startHour) + ":" + Utils.TwoDigits(oh.startMinutes)).SetClass("oh-timerange-label")
 | 
					        const startTime = new FixedUiElement(Utils.TwoDigits(oh.startHour) + ":" + Utils.TwoDigits(oh.startMinutes))
 | 
				
			||||||
        const endTime = new FixedUiElement(Utils.TwoDigits(oh.endHour) + ":" + Utils.TwoDigits(oh.endMinutes)).SetClass("oh-timerange-label")
 | 
					        const endTime = new FixedUiElement(Utils.TwoDigits(oh.endHour) + ":" + Utils.TwoDigits(oh.endMinutes))
 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        const deleteRange =
 | 
					        const deleteRange =
 | 
				
			||||||
            Svg.delete_icon_ui()
 | 
					            Svg.delete_icon_ui()
 | 
				
			||||||
                .SetClass("oh-delete-range")
 | 
					                .SetClass("rounded-full w-6 h-6 block bg-black")
 | 
				
			||||||
                .onClick(() => {
 | 
					                .onClick(() => {
 | 
				
			||||||
                    this._onDelete()
 | 
					                    this._onDelete()
 | 
				
			||||||
                });
 | 
					                });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        let content = [deleteRange]
 | 
					        let content: BaseUIElement;
 | 
				
			||||||
        if (height > 2) {
 | 
					        if (height > 2) {
 | 
				
			||||||
            content = [startTime, deleteRange, endTime];
 | 
					            content = new Combine([startTime, deleteRange, endTime]).SetClass("flex flex-col h-full").SetStyle("justify-content: space-between;");
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					            content = new Combine([deleteRange]).SetClass("flex flex-col h-full").SetStyle("flex-content: center; overflow-x: unset;")
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        const el = new Combine(content)
 | 
					        const el = new Combine([content]).ConstructElement();
 | 
				
			||||||
            .SetClass("oh-timerange-inner").ConstructElement();
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        el.style.top = (100 * OH.startTime(oh) / 24) + "%"
 | 
					        el.style.top = `${100 * OH.startTime(oh) / 24}%`
 | 
				
			||||||
        el.style.height = (100 * (OH.endTime(oh) - OH.startTime(oh)) / 24) + "%"
 | 
					        el.style.height = `${100 * this.getHeight() / 24}%`
 | 
				
			||||||
        return el;
 | 
					        return el;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -5,166 +5,19 @@ import {TextField} from "../Input/TextField";
 | 
				
			||||||
import {DropDown} from "../Input/DropDown";
 | 
					import {DropDown} from "../Input/DropDown";
 | 
				
			||||||
import {InputElement} from "../Input/InputElement";
 | 
					import {InputElement} from "../Input/InputElement";
 | 
				
			||||||
import Translations from "../i18n/Translations";
 | 
					import Translations from "../i18n/Translations";
 | 
				
			||||||
import BaseUIElement from "../BaseUIElement";
 | 
					import Toggle from "../Input/Toggle";
 | 
				
			||||||
import {VariableUiElement} from "../Base/VariableUIElement";
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
export default class PublicHolidayInput extends InputElement<string> {
 | 
					export default class PublicHolidayInput extends InputElement<string> {
 | 
				
			||||||
    IsSelected: UIEventSource<boolean> = new UIEventSource<boolean>(false);
 | 
					    IsSelected: UIEventSource<boolean> = new UIEventSource<boolean>(false);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    private readonly _value: UIEventSource<string>;
 | 
					    private readonly _value: UIEventSource<string>;
 | 
				
			||||||
    private readonly _dropdown: BaseUIElement;
 | 
					 | 
				
			||||||
    private readonly _mode: UIEventSource<string>;
 | 
					 | 
				
			||||||
    private readonly _startHour: BaseUIElement;
 | 
					 | 
				
			||||||
    private readonly _endHour: BaseUIElement;
 | 
					 | 
				
			||||||
    private _element: VariableUiElement;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    constructor(value: UIEventSource<string> = new UIEventSource<string>("")) {
 | 
					    constructor(value: UIEventSource<string> = new UIEventSource<string>("")) {
 | 
				
			||||||
        super();
 | 
					        super();
 | 
				
			||||||
        this._value = value;
 | 
					        this._value = value;
 | 
				
			||||||
 | 
					 | 
				
			||||||
        const dropdown = new DropDown(
 | 
					 | 
				
			||||||
            Translations.t.general.opening_hours.open_during_ph,
 | 
					 | 
				
			||||||
            [
 | 
					 | 
				
			||||||
                {shown: Translations.t.general.opening_hours.ph_not_known, value: ""},
 | 
					 | 
				
			||||||
                {shown: Translations.t.general.opening_hours.ph_closed, value: "off"},
 | 
					 | 
				
			||||||
                {shown:Translations.t.general.opening_hours.ph_open, value: " "}
 | 
					 | 
				
			||||||
            ]
 | 
					 | 
				
			||||||
        );
 | 
					 | 
				
			||||||
        this._dropdown = dropdown.SetStyle("display:inline-block;");
 | 
					 | 
				
			||||||
        this._mode = dropdown.GetValue();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        const start = new TextField({
 | 
					 | 
				
			||||||
            placeholder: "starthour",
 | 
					 | 
				
			||||||
            htmlType: "time"
 | 
					 | 
				
			||||||
        });
 | 
					 | 
				
			||||||
        const end = new TextField({
 | 
					 | 
				
			||||||
            placeholder: "starthour",
 | 
					 | 
				
			||||||
            htmlType: "time"
 | 
					 | 
				
			||||||
        });
 | 
					 | 
				
			||||||
        this._startHour = start.SetStyle("display:inline-block;");
 | 
					 | 
				
			||||||
        this._endHour = end.SetStyle("display:inline-block;");
 | 
					 | 
				
			||||||
        const self = this;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        this._value.addCallbackAndRun(ph => {
 | 
					 | 
				
			||||||
            if (ph === undefined) {
 | 
					 | 
				
			||||||
                return;
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
            const parsed = PublicHolidayInput.LoadValue(ph);
 | 
					 | 
				
			||||||
            if (parsed === null) {
 | 
					 | 
				
			||||||
                return;
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            dropdown.GetValue().setData(parsed.mode);
 | 
					 | 
				
			||||||
            if (parsed.start) {
 | 
					 | 
				
			||||||
                start.GetValue().setData(parsed.start);
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
            if (parsed.end) {
 | 
					 | 
				
			||||||
                end.GetValue().setData(parsed.end);
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        })
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        function updateValue() {
 | 
					 | 
				
			||||||
            const phStart = dropdown.GetValue().data;
 | 
					 | 
				
			||||||
            if (phStart === undefined || phStart === "") {
 | 
					 | 
				
			||||||
                // Unknown
 | 
					 | 
				
			||||||
                self._value.setData("");
 | 
					 | 
				
			||||||
                return;
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            if (phStart === " ") {
 | 
					 | 
				
			||||||
                // THey are open, we need to include the start- and enddate
 | 
					 | 
				
			||||||
                const startV = start.GetValue().data;
 | 
					 | 
				
			||||||
                const endV = end.GetValue().data;
 | 
					 | 
				
			||||||
                if (startV === undefined || endV === undefined) {
 | 
					 | 
				
			||||||
                    self._value.setData(`PH open`);
 | 
					 | 
				
			||||||
                    return;
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                self._value.setData(`PH ${startV}-${endV}`);
 | 
					 | 
				
			||||||
                return;
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
            self._value.setData(`PH ${phStart}`);
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        dropdown.GetValue().addCallbackAndRun(() => {
 | 
					 | 
				
			||||||
            updateValue();
 | 
					 | 
				
			||||||
        });
 | 
					 | 
				
			||||||
        start.GetValue().addCallbackAndRun(() => {
 | 
					 | 
				
			||||||
            updateValue();
 | 
					 | 
				
			||||||
        });
 | 
					 | 
				
			||||||
        end.GetValue().addCallbackAndRun(() => {
 | 
					 | 
				
			||||||
            updateValue();
 | 
					 | 
				
			||||||
        });
 | 
					 | 
				
			||||||
        
 | 
					 | 
				
			||||||
        this._element = new VariableUiElement(this._mode.map(
 | 
					 | 
				
			||||||
            mode => {
 | 
					 | 
				
			||||||
                if (mode === " ") {
 | 
					 | 
				
			||||||
                    return new Combine([this._dropdown,
 | 
					 | 
				
			||||||
                        " ",
 | 
					 | 
				
			||||||
                        Translations.t.general.opening_hours.opensAt,
 | 
					 | 
				
			||||||
                        " ",
 | 
					 | 
				
			||||||
                        this._startHour,
 | 
					 | 
				
			||||||
                        " ",
 | 
					 | 
				
			||||||
                        Translations.t.general.opening_hours.openTill,
 | 
					 | 
				
			||||||
                        " ",
 | 
					 | 
				
			||||||
                        this._endHour]);
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
                return this._dropdown;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            }))
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    protected InnerConstructElement(): HTMLElement {
 | 
					   
 | 
				
			||||||
        return this._element.ConstructElement();
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    public static LoadValue(str: string): {
 | 
					 | 
				
			||||||
        mode: string,
 | 
					 | 
				
			||||||
        start?: string,
 | 
					 | 
				
			||||||
        end?: string
 | 
					 | 
				
			||||||
    } {
 | 
					 | 
				
			||||||
        str = str.trim();
 | 
					 | 
				
			||||||
        if (!str.startsWith("PH")) {
 | 
					 | 
				
			||||||
            return null;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        str = str.trim();
 | 
					 | 
				
			||||||
        if (str === "PH off") {
 | 
					 | 
				
			||||||
            return {
 | 
					 | 
				
			||||||
                mode: "off"
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        
 | 
					 | 
				
			||||||
        if(str === "PH open"){
 | 
					 | 
				
			||||||
            return {
 | 
					 | 
				
			||||||
                mode: " "
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        if (!str.startsWith("PH ")) {
 | 
					 | 
				
			||||||
            return null;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        try {
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            const timerange = OH.parseHHMMRange(str.substring(2));
 | 
					 | 
				
			||||||
            if (timerange === null) {
 | 
					 | 
				
			||||||
                return null;
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            return {
 | 
					 | 
				
			||||||
                mode: " ",
 | 
					 | 
				
			||||||
                start: OH.hhmm(timerange.startHour, timerange.startMinutes),
 | 
					 | 
				
			||||||
                end: OH.hhmm(timerange.endHour, timerange.endMinutes),
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        } catch (e) {
 | 
					 | 
				
			||||||
            return null;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    GetValue(): UIEventSource<string> {
 | 
					    GetValue(): UIEventSource<string> {
 | 
				
			||||||
        return this._value;
 | 
					        return this._value;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
| 
						 | 
					@ -172,5 +25,97 @@ export default class PublicHolidayInput extends InputElement<string> {
 | 
				
			||||||
    IsValid(t: string): boolean {
 | 
					    IsValid(t: string): boolean {
 | 
				
			||||||
        return true;
 | 
					        return true;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    private SetupDataSync(mode: UIEventSource<string>, startTime: UIEventSource<string>, endTime: UIEventSource<string>) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        const value = this._value;
 | 
				
			||||||
 | 
					        value.addCallbackAndRun(ph => {
 | 
				
			||||||
 | 
					            if (ph === undefined) {
 | 
				
			||||||
 | 
					                return;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            const parsed = OH.ParsePHRule(ph);
 | 
				
			||||||
 | 
					            if (parsed === null) {
 | 
				
			||||||
 | 
					                return;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            mode.setData(parsed.mode)
 | 
				
			||||||
 | 
					            startTime.setData(parsed.start)
 | 
				
			||||||
 | 
					            endTime.setData(parsed.end)
 | 
				
			||||||
 | 
					        })
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // We use this as a 'addCallbackAndRun'
 | 
				
			||||||
 | 
					        mode.map(mode => {
 | 
				
			||||||
 | 
					                if (mode === undefined || mode === "") {
 | 
				
			||||||
 | 
					                    // not known
 | 
				
			||||||
 | 
					                    value.setData(undefined)
 | 
				
			||||||
 | 
					                    return
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					                if (mode === "off") {
 | 
				
			||||||
 | 
					                    value.setData("PH off");
 | 
				
			||||||
 | 
					                    return;
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					                if (mode === "open") {
 | 
				
			||||||
 | 
					                    value.setData("PH open");
 | 
				
			||||||
 | 
					                    return;
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                // Open during PH with special hours
 | 
				
			||||||
 | 
					                if (startTime.data === undefined || endTime.data === undefined) {
 | 
				
			||||||
 | 
					                    // hours not filled in - not saveable
 | 
				
			||||||
 | 
					                    value.setData(undefined)
 | 
				
			||||||
 | 
					                    return
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					                const oh = `PH ${startTime.data}-${endTime.data}`
 | 
				
			||||||
 | 
					                value.setData(oh)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            }, [startTime, endTime]
 | 
				
			||||||
 | 
					        )
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    protected InnerConstructElement(): HTMLElement {
 | 
				
			||||||
 | 
					        const dropdown = new DropDown(
 | 
				
			||||||
 | 
					            Translations.t.general.opening_hours.open_during_ph.Clone(),
 | 
				
			||||||
 | 
					            [
 | 
				
			||||||
 | 
					                {shown: Translations.t.general.opening_hours.ph_not_known.Clone(), value: ""},
 | 
				
			||||||
 | 
					                {shown: Translations.t.general.opening_hours.ph_closed.Clone(), value: "off"},
 | 
				
			||||||
 | 
					                {shown:Translations.t.general.opening_hours.ph_open_as_usual.Clone(), value: "open"},
 | 
				
			||||||
 | 
					                {shown: Translations.t.general.opening_hours.ph_open.Clone(), value: " "},
 | 
				
			||||||
 | 
					            ]
 | 
				
			||||||
 | 
					        ).SetClass("inline-block");
 | 
				
			||||||
 | 
					        /*
 | 
				
			||||||
 | 
					        * Either "" (unknown), " " (opened) or "off" (closed)
 | 
				
			||||||
 | 
					        * */
 | 
				
			||||||
 | 
					        const mode = dropdown.GetValue();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        const start = new TextField({
 | 
				
			||||||
 | 
					            placeholder: "starthour",
 | 
				
			||||||
 | 
					            htmlType: "time"
 | 
				
			||||||
 | 
					        }).SetClass("inline-block");
 | 
				
			||||||
 | 
					        const end = new TextField({
 | 
				
			||||||
 | 
					            placeholder: "starthour",
 | 
				
			||||||
 | 
					            htmlType: "time"
 | 
				
			||||||
 | 
					        }).SetClass("inline-block");
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        const askHours = new Toggle(
 | 
				
			||||||
 | 
					            new Combine([
 | 
				
			||||||
 | 
					                Translations.t.general.opening_hours.opensAt.Clone(),
 | 
				
			||||||
 | 
					                start,
 | 
				
			||||||
 | 
					                Translations.t.general.opening_hours.openTill.Clone(),
 | 
				
			||||||
 | 
					                end
 | 
				
			||||||
 | 
					            ]),
 | 
				
			||||||
 | 
					            undefined,
 | 
				
			||||||
 | 
					            mode.map(mode => mode === " ")
 | 
				
			||||||
 | 
					        )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        this.SetupDataSync(mode, start.GetValue(), end.GetValue())
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        return new Combine([
 | 
				
			||||||
 | 
					            dropdown,
 | 
				
			||||||
 | 
					            askHours
 | 
				
			||||||
 | 
					        ]).ConstructElement()
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -64,6 +64,7 @@
 | 
				
			||||||
    font-size: large;
 | 
					    font-size: large;
 | 
				
			||||||
    padding: 0;
 | 
					    padding: 0;
 | 
				
			||||||
    padding-right: 0.2em;
 | 
					    padding-right: 0.2em;
 | 
				
			||||||
 | 
					    box-sizing: border-box;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
.oh-timecell-0 {
 | 
					.oh-timecell-0 {
 | 
				
			||||||
| 
						 | 
					@ -119,35 +120,6 @@
 | 
				
			||||||
    overflow: unset;
 | 
					    overflow: unset;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
.oh-timerange-inner {
 | 
					 | 
				
			||||||
    display: flex;
 | 
					 | 
				
			||||||
    flex-direction: column;
 | 
					 | 
				
			||||||
    justify-content: center;
 | 
					 | 
				
			||||||
    align-content: center;
 | 
					 | 
				
			||||||
    height: 100%;
 | 
					 | 
				
			||||||
    overflow-x: unset;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
.oh-timerange-inner-small {
 | 
					 | 
				
			||||||
    display: flex;
 | 
					 | 
				
			||||||
    flex-direction: row;
 | 
					 | 
				
			||||||
    justify-content: space-between;
 | 
					 | 
				
			||||||
    height: 100%;
 | 
					 | 
				
			||||||
    width:100%;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
.oh-delete-range{
 | 
					 | 
				
			||||||
    width: 1.5em;
 | 
					 | 
				
			||||||
    height: 1.5em;
 | 
					 | 
				
			||||||
    background:black;
 | 
					 | 
				
			||||||
    border-radius:0.75em;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
.oh-delete-range img {
 | 
					 | 
				
			||||||
    height: 100%;
 | 
					 | 
				
			||||||
    max-width: 2em;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/**** Opening hours visualization table ****/
 | 
					/**** Opening hours visualization table ****/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
.ohviz-table {
 | 
					.ohviz-table {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -151,7 +151,8 @@
 | 
				
			||||||
            "open_24_7": "Opened around the clock",
 | 
					            "open_24_7": "Opened around the clock",
 | 
				
			||||||
            "ph_not_known": " ",
 | 
					            "ph_not_known": " ",
 | 
				
			||||||
            "ph_closed": "closed",
 | 
					            "ph_closed": "closed",
 | 
				
			||||||
            "ph_open": "opened"
 | 
					            "ph_open": "opened with different hours",
 | 
				
			||||||
 | 
					            "ph_open_as_usual": "opened as usual"
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    "favourite": {
 | 
					    "favourite": {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										12
									
								
								test.ts
									
										
									
									
									
								
							
							
						
						
									
										12
									
								
								test.ts
									
										
									
									
									
								
							| 
						 | 
					@ -8,6 +8,7 @@ import OpeningHoursPickerTable from "./UI/OpeningHours/OpeningHoursPickerTable";
 | 
				
			||||||
import OpeningHoursPicker from "./UI/OpeningHours/OpeningHoursPicker";
 | 
					import OpeningHoursPicker from "./UI/OpeningHours/OpeningHoursPicker";
 | 
				
			||||||
import {OH, OpeningHour} from "./UI/OpeningHours/OpeningHours";
 | 
					import {OH, OpeningHour} from "./UI/OpeningHours/OpeningHours";
 | 
				
			||||||
import {VariableUiElement} from "./UI/Base/VariableUIElement";
 | 
					import {VariableUiElement} from "./UI/Base/VariableUIElement";
 | 
				
			||||||
 | 
					import PublicHolidayInput from "./UI/OpeningHours/PublicHolidayInput";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const tagsSource = new UIEventSource({
 | 
					const tagsSource = new UIEventSource({
 | 
				
			||||||
| 
						 | 
					@ -23,15 +24,8 @@ const tagsSource = new UIEventSource({
 | 
				
			||||||
const state = new State(undefined)
 | 
					const state = new State(undefined)
 | 
				
			||||||
State.state = state
 | 
					State.state = state
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const ohData = new UIEventSource<OpeningHour[]>([{
 | 
					const ohData = new UIEventSource<string>("")
 | 
				
			||||||
    weekday: 1,
 | 
					new OpeningHoursPicker().AttachTo("maindiv")
 | 
				
			||||||
    startHour: 10,
 | 
					 | 
				
			||||||
    startMinutes: 0
 | 
					 | 
				
			||||||
    , endHour: 12,
 | 
					 | 
				
			||||||
    endMinutes: 0
 | 
					 | 
				
			||||||
}])
 | 
					 | 
				
			||||||
new OpeningHoursPicker(ohData).AttachTo("maindiv")
 | 
					 | 
				
			||||||
new VariableUiElement(ohData.map(OH.ToString)).AttachTo("extradiv")
 | 
					 | 
				
			||||||
/*
 | 
					/*
 | 
				
			||||||
const allSpecials = SpecialVisualizations.specialVisualizations.map(spec => {
 | 
					const allSpecials = SpecialVisualizations.specialVisualizations.map(spec => {
 | 
				
			||||||
    try{
 | 
					    try{
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -352,6 +352,47 @@ export default class    TagSpec extends  T{
 | 
				
			||||||
                ]);
 | 
					                ]);
 | 
				
			||||||
                equal(rules, "Tu 10:00-12:00; Su 13:00-17:00");
 | 
					                equal(rules, "Tu 10:00-12:00; Su 13:00-17:00");
 | 
				
			||||||
            }],
 | 
					            }],
 | 
				
			||||||
 | 
					            ["JOIN OH with end hours", () =>{
 | 
				
			||||||
 | 
					                const rules = OH.ToString(
 | 
				
			||||||
 | 
					                    OH.MergeTimes([
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                    {
 | 
				
			||||||
 | 
					                        weekday: 1,
 | 
				
			||||||
 | 
					                        endHour: 23,
 | 
				
			||||||
 | 
					                        endMinutes: 30,
 | 
				
			||||||
 | 
					                        startHour: 23,
 | 
				
			||||||
 | 
					                        startMinutes: 0
 | 
				
			||||||
 | 
					                    }, {
 | 
				
			||||||
 | 
					                        weekday: 1,
 | 
				
			||||||
 | 
					                        endHour: 24,
 | 
				
			||||||
 | 
					                        endMinutes: 0,
 | 
				
			||||||
 | 
					                        startHour: 23,
 | 
				
			||||||
 | 
					                        startMinutes: 30
 | 
				
			||||||
 | 
					                    },
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                ]));
 | 
				
			||||||
 | 
					                equal(rules, "Tu 23:00-00:00");
 | 
				
			||||||
 | 
					            }],            ["JOIN OH with overflowed hours", () =>{
 | 
				
			||||||
 | 
					                const rules = OH.ToString(
 | 
				
			||||||
 | 
					                    OH.MergeTimes([
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                        {
 | 
				
			||||||
 | 
					                            weekday: 1,
 | 
				
			||||||
 | 
					                            endHour: 23,
 | 
				
			||||||
 | 
					                            endMinutes: 30,
 | 
				
			||||||
 | 
					                            startHour: 23,
 | 
				
			||||||
 | 
					                            startMinutes: 0
 | 
				
			||||||
 | 
					                        }, {
 | 
				
			||||||
 | 
					                            weekday: 1,
 | 
				
			||||||
 | 
					                            endHour: 0,
 | 
				
			||||||
 | 
					                            endMinutes: 0,
 | 
				
			||||||
 | 
					                            startHour: 23,
 | 
				
			||||||
 | 
					                            startMinutes: 30
 | 
				
			||||||
 | 
					                        },
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                    ]));
 | 
				
			||||||
 | 
					                equal(rules, "Tu 23:00-00:00");
 | 
				
			||||||
 | 
					            }],
 | 
				
			||||||
            ["OH 24/7", () => {
 | 
					            ["OH 24/7", () => {
 | 
				
			||||||
                const rules = OH.Parse("24/7");
 | 
					                const rules = OH.Parse("24/7");
 | 
				
			||||||
                equal(rules.length, 7);
 | 
					                equal(rules.length, 7);
 | 
				
			||||||
| 
						 | 
					@ -368,8 +409,10 @@ export default class    TagSpec extends  T{
 | 
				
			||||||
                equal(rules, null);
 | 
					                equal(rules, null);
 | 
				
			||||||
            }],
 | 
					            }],
 | 
				
			||||||
            ["OH Parse PH 12:00-17:00", () => {
 | 
					            ["OH Parse PH 12:00-17:00", () => {
 | 
				
			||||||
                const rules = PublicHolidayInput.LoadValue("PH 12:00-17:00");
 | 
					                const rules = OH.ParsePHRule("PH 12:00-17:00");
 | 
				
			||||||
                equal(rules.mode, " ");
 | 
					                equal(rules.mode, " ");
 | 
				
			||||||
 | 
					                equal(rules.start, "12:00")
 | 
				
			||||||
 | 
					                equal(rules.end, "17:00")
 | 
				
			||||||
            }],
 | 
					            }],
 | 
				
			||||||
            ["Round", () => {
 | 
					            ["Round", () => {
 | 
				
			||||||
                equal(Utils.Round(15), "15.0")
 | 
					                equal(Utils.Round(15), "15.0")
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue