if (!String.prototype.includes) { String.prototype.includes = function () { 'use strict'; return String.prototype.indexOf.apply(this, arguments) !== -1; }; } //extend FileReader if (!FileReader.prototype.readAsBinaryString) { FileReader.prototype.readAsBinaryString = function (fileData) { var binary = ""; var pt = this; var reader = new FileReader(); reader.onload = function (e) { var bytes = new Uint8Array(reader.result); var length = bytes.byteLength; for (var i = 0; i < length; i++) { binary += String.fromCharCode(bytes[i]); } //pt.result - readonly so assign binary pt.content = binary; $(pt).trigger('onload'); } reader.readAsArrayBuffer(file); } } var options = { timepicker: { twelveHour: false, } }; document.addEventListener('DOMContentLoaded', function() { M.AutoInit(); var elems = document.querySelectorAll('.timepicker'); var timepickers = M.Timepicker.init(elems, options.timepicker); }); //localStorage persistence var SHIFT_STORAGE_KEY = "dienstplan_chrosey"; var RULE_STORAGE_KEY = "regeln_chrosey"; var shiftStorage = { fetch: function () { 'use strict'; var parsed = JSON.parse(localStorage.getItem(SHIFT_STORAGE_KEY) || '[]'), shifts = []; parsed.forEach(function (el, index) { var shift = Shift.thaw(el); shift.id = index; shifts.push(shift); }); shiftStorage.uid = shifts.length; return shifts; }, save: function (shifts) { 'use strict'; var json = JSON.stringify(shifts) localStorage.setItem(SHIFT_STORAGE_KEY, json); }, count: function () { return JSON.parse(localStorage.getItem(SHIFT_STORAGE_KEY) || '[]').length; } }; var ruleStorage = { fetch: function () { 'use strict'; var parsed = JSON.parse(localStorage.getItem(RULE_STORAGE_KEY)) | []; var rules = parsed.length > 0 ? parsed.map((e,i) => { var r = Rule.thaw(e); r.id = i; return r; }) : Rule.defaults(); ruleStorage.uid = rules.length; return rules; }, save: function (rules) { 'use strict'; var json = JSON.stringify(rules); localStorage.setItem(RULE_STORAGE_KEY, json); } }; Vue.component('chip-input', { template: `
`, data() { return { instance: null, chips: [] } }, computed: { chipsData() { return this.instance.chipsData; } }, watch:{ initData:{ deep: true, handler(n,o) { if (n !== o) { this.initialize(); this.$emit('init'); } } } }, props: { name: String, initData: Array }, methods: { initialize() { this.chips = this.initData.map(e => e); var el = $('#'+this.name)[0]; this.instance = M.Chips.init(el, { data: this.chips, onChipAdd: () => { this.$emit("change",this.chipsData); }, onChipDelete: () => { this.$emit("change",this.chipsData); } }); } }, mounted() { this.initialize(); } }); var app = new Vue({ el: '#app', data: { shifts: shiftStorage.fetch(), rules: ruleStorage.fetch(), icsFile: null, blob: null, dp_sheet: '', deletedShift: '', remaining: shiftStorage.count(), selectedShift: new Shift({}), selectedShiftIndex: -1, selectedRule: new Rule({}), selectedRuleIndex: -1, saveto: 'dienstplan.ics', uploadFileName: "", config: { moment: { parse_formats: [ "ddd, DD/ MMM. 'YY HH:mm", "ddd, DD/ MMM. YYYY HH:mm" ], parse_language: 'en', display_language: 'de' }, toast_length: 3000 }, }, watch: { shifts: { handler: function (shifts) { 'use strict'; shiftStorage.save(shifts); this.remaining = shifts.length; this.makeToast("Änderungen gespeichert."); }, deep: true }, rules: { handler: function (rules) { 'use strict'; ruleStorage.save(rules); this.makeToast("Änderungen gespeichert."); }, deep: true } }, methods: { updateArten(value){ this.selectedRule.Arten = value; }, updateTitel(value){ this.selectedRule.Titel = value; }, makeToast(message) { M.toast({ html: message, displayLength: this.config.toast_length }); }, onFileChange: function (event) { var files = event.target.files || event.dataTransfer.files; this.handleInputFile(files[0]); this.uploadFileName = files[0].name + " [" + Math.round(files[0].size / 1024) + " kB]"; this.makeToast(this.uploadFileName + " ausgewählt"); }, handleInputFile: function (file) { var reader = new FileReader(); var vm = this; reader.onload = (e) => { var data = !e ? reader.content : e.target.result; var workbook = XLSX.read(data, { type: 'binary', cellDates: true, }); var isErfurterDienstplan = workbook.SheetNames.indexOf("Dienstplan") > -1; if(isErfurterDienstplan){ vm.parseForErfurt(workbook.Sheets["Dienstplan"]); } else { var sheetName = workbook.SheetNames[0]; vm.parseForStuttgart(workbook.Sheets[sheetName]); } }; reader.readAsBinaryString(file); }, parseForErfurt: function (dp) { var arr = XLSX.utils.sheet_to_row_object_array(dp, { range: 1 }); var vm = this; var day; this.makeToast("Erfurter Dienstplan erkannt."); arr.forEach(element => { moment.locale(vm.config.moment.parse_language); if (element.hasOwnProperty('Datum')) { day = moment(element.Datum); } if (element.hasOwnProperty('Dienst')) { var time = element.Zeit ? moment(element.Zeit) : day; var termin = { datum: day.clone().hour(time.hour()).minute(time.minute()), art: element.Dienst ? element.Dienst.trim() : "", beschreibung: element.Bemerkung ? element.Bemerkung.trim(): "", name: element.__EMPTY ? element.__EMPTY.trim() : "" } vm.addShift(new Shift(termin)); } }); }, parseForStuttgart: function (dp) { var arr = XLSX.utils.sheet_to_json(dp, { header: "A", blankrows: false, }); var vm = this; var day; this.makeToast("Stuttgarter Dienstplan erkannt."); arr.forEach(element => { moment.locale(vm.config.moment.parse_language); if (element.hasOwnProperty('C')) { day = moment(element.C); } if (element.hasOwnProperty('D') && moment(element.D, "HH:mm").isValid()) { var termin = { ort: element.H ? element.H.trim() : "", art: element.E ? element.E.trim() : "", beschreibung: element.H ? element.H.trim(): "", name: element.F ? element.F.trim() : "" } var time = day.clone(); if (typeof(element.D) === "object") { time = moment(element.D); termin.datum = day.clone().hour(time.hour()).minute(time.minute()); } else if(element.D.indexOf("-") > -1 ) { var tArray = element.D.split(" - "); time = moment(tArray[0],"HH:mm"); termin.datum = day.clone().hour(time.hour()).minute(time.minute()); termin.ende = moment(tArray[1], "HH:mm").format("HH:mm"); } vm.addShift(new Shift(termin)); } }); }, addShift: function (shift) { this.shifts.push(shift); }, removeShift: function (shift) { this.shifts.splice(this.shifts.indexOf(shift), 1); this.makeToast(shift.VEventTitle + " gelöscht"); }, cleanStorage: function () { this.shifts = []; this.makeToast("Alle Einträge gelöscht"); }, createDownloadFile: function () { var vCal = new VCalendar("Dienstplan Kalender"); this.shifts.forEach(function (shift) { vCal.add(shift.toVEvent()); }); var calString = vCal.toString(); this.blob = new Blob([calString], { type: 'text/plain' }); if (this.icsFile !== null) { window.URL.revokeObjectURL(this.icsFile); } this.icsFile = window.URL.createObjectURL(this.blob); this.makeToast(this.saveto + " erstellt."); }, downloadFile: function () { if (window.navigator.msSaveOrOpenBlob) { window.navigator.msSaveOrOpenBlob(this.blob, this.saveto); } }, selectShift: function (shift) { this.selectedShift = Shift.thaw(shift); this.keepShift = shift; M.updateTextFields(); $('#shiftModal').modal('open'); }, saveChanges: function (changedShift) { this.shifts.splice(this.shifts.indexOf(this.keepShift), 1, changedShift); $('#shiftModal').modal('close'); this.keepShift = ''; this.selectedShift = ''; }, discardChanges: function (changedShift) { $('#shiftModal').modal('close'); this.keepShift = ''; this.selectedShift = ''; }, editRule: function (rule) { this.selectedRule = Rule.thaw(rule); this.selectedRuleIndex = this.rules.indexOf(rule); $('#ruleModal').modal('open'); }, saveRule: function () { this.rules[this.selectedRuleIndex] = this.selectedRule; $('#ruleModal').modal('close'); this.selectedRule = new Rule(); }, discardRule: function () { $('#ruleModal').modal('close'); this.selectedRule = new Rule(); } }, directives: { 'edit-focus': function (el, value) { if (value) { el.focus(); } } } })