Merge pull request 'task-stepper' (#1) from task-stepper into master
Reviewed-on: #1
This commit is contained in:
commit
67674f1a67
172
app.js
172
app.js
@ -24,19 +24,7 @@ if (!FileReader.prototype.readAsBinaryString) {
|
||||
}
|
||||
}
|
||||
|
||||
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 = {
|
||||
@ -65,13 +53,13 @@ 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 rules = parsed.length > 0 ?
|
||||
parsed.map((e, i) => {
|
||||
var r = Rule.thaw(e);
|
||||
r.id = i;
|
||||
return r;
|
||||
})
|
||||
: Rule.defaults();
|
||||
}) :
|
||||
Rule.defaults();
|
||||
ruleStorage.uid = rules.length;
|
||||
return rules;
|
||||
},
|
||||
@ -177,6 +165,7 @@ var app = new Vue({
|
||||
blob: null,
|
||||
dp_sheet: '',
|
||||
deletedShift: '',
|
||||
format: '',
|
||||
remaining: shiftStorage.count(),
|
||||
selectedShift: new Shift({}),
|
||||
selectedShiftIndex: -1,
|
||||
@ -185,6 +174,9 @@ var app = new Vue({
|
||||
saveto: 'dienstplan.ics',
|
||||
uploadFileName: "",
|
||||
availableFormats: ["Erfurt", "Stuttgart", "X"],
|
||||
stepper: null,
|
||||
timepickers: null,
|
||||
|
||||
config: {
|
||||
moment: {
|
||||
parse_formats: [
|
||||
@ -194,11 +186,16 @@ var app = new Vue({
|
||||
parse_language: 'en',
|
||||
display_language: 'de'
|
||||
},
|
||||
stepper: {
|
||||
firstActive: 0,
|
||||
},
|
||||
toast: {
|
||||
displayLength: 3000
|
||||
},
|
||||
timepicker: {
|
||||
twelveHour: false,
|
||||
}
|
||||
},
|
||||
workbook: null,
|
||||
},
|
||||
watch: {
|
||||
shifts: {
|
||||
@ -206,6 +203,8 @@ var app = new Vue({
|
||||
'use strict';
|
||||
shiftStorage.save(shifts);
|
||||
this.remaining = shifts.length;
|
||||
this.icsFile = null;
|
||||
this.blob = null;
|
||||
this.makeToast("Änderungen gespeichert.");
|
||||
},
|
||||
deep: true
|
||||
@ -222,7 +221,7 @@ var app = new Vue({
|
||||
|
||||
computed: {
|
||||
groupedTermine() {
|
||||
return _.groupBy(this.shifts, e => e.Datum);
|
||||
return _.chain(this.shifts).sortBy(e => e.Datum).groupBy(e => e.Datum).value();
|
||||
}
|
||||
},
|
||||
|
||||
@ -241,6 +240,19 @@ var app = new Vue({
|
||||
M.toast(toastOptions);
|
||||
},
|
||||
|
||||
openModal(elementID) {
|
||||
var element = document.getElementById(elementID);
|
||||
var modal = M.Modal.getInstance(element);
|
||||
modal.open();
|
||||
},
|
||||
|
||||
closeModal(elementID) {
|
||||
var element = document.getElementById(elementID);
|
||||
var modal = M.Modal.getInstance(element);
|
||||
modal.close();
|
||||
},
|
||||
|
||||
|
||||
onFileChange: function (event) {
|
||||
var files = event.target.files || event.dataTransfer.files;
|
||||
this.handleInputFile(files[0]);
|
||||
@ -271,13 +283,14 @@ var app = new Vue({
|
||||
|
||||
askForDienstplanFormat: function () {
|
||||
this.makeToast("Dienstplanformat nicht erkannt.");
|
||||
$('#ask-format-modal').modal("open");
|
||||
this.openModal('ask-format-modal');
|
||||
},
|
||||
|
||||
parseForErfurt: function (dp) {
|
||||
var arr = XLSX.utils.sheet_to_row_object_array(dp, {
|
||||
range: 1
|
||||
});
|
||||
this.format = "Erfurt";
|
||||
var vm = this;
|
||||
var day;
|
||||
|
||||
@ -289,18 +302,75 @@ var app = new Vue({
|
||||
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() : ""
|
||||
|
||||
let times = [];
|
||||
let art, beschreibung, name = "";
|
||||
if (element.Zeit.toString().indexOf(' + ') > 0) {
|
||||
// in der Zeitspalte stehen mehrere Uhrzeiten.
|
||||
let tempTimes = element.Zeit.toString().split(' + ');
|
||||
tempTimes.forEach(function(time) {
|
||||
let mom = moment(time, 'HH:mm');
|
||||
times.push([mom.hour(), mom.minute()]);
|
||||
})
|
||||
} else {
|
||||
if (element.Zeit) {
|
||||
let mom = moment(element.Zeit);
|
||||
times.push([mom.hour(), mom.minute()]);
|
||||
} else {
|
||||
times.push([0,0]);
|
||||
}
|
||||
}
|
||||
if (element.hasOwnProperty('Bemerkung')) {
|
||||
if (element.Bemerkung.toString().search(/\d\d:\d\d\s/) >= 0) {
|
||||
// prüfe ob eine Uhrzeit drinnen steht
|
||||
let sonderzeit = moment(element.Bemerkung, 'HH:mm');
|
||||
let termin = {
|
||||
datum: day.clone().hour(sonderzeit.hour()).minute(sonderzeit.minute()),
|
||||
art: '',
|
||||
beschreibung: '',
|
||||
name: element.Bemerkung.toString().replace(/\d\d:\d\d\s/, '').trim()
|
||||
}
|
||||
vm.addShift(new Shift(termin));
|
||||
beschreibung = '';
|
||||
} else {
|
||||
beschreibung = element.Bemerkung;
|
||||
}
|
||||
}
|
||||
if (element.hasOwnProperty('Dienst')) {
|
||||
art = element.Dienst.trim();
|
||||
}
|
||||
if (element.hasOwnProperty('__EMPTY')) {
|
||||
name = element.__EMPTY.trim();
|
||||
}
|
||||
|
||||
times.forEach(time => {
|
||||
var termin = {
|
||||
datum: day.clone().hour(time[0]).minute(time[1]),
|
||||
art: art,
|
||||
beschreibung: beschreibung,
|
||||
name: name
|
||||
}
|
||||
vm.addShift(new Shift(termin));
|
||||
});
|
||||
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
changeTime: function (hours) {
|
||||
let temp = this.shifts;
|
||||
this.shifts = [];
|
||||
temp.forEach(shift => {
|
||||
shift.updateBeginn(hours);
|
||||
this.addShift(shift);
|
||||
});
|
||||
},
|
||||
|
||||
updateBeginn: function (shift, hours) {
|
||||
shift.updateBeginn(hours);
|
||||
this.shifts.splice(this.shifts.indexOf(shift), 1, shift);
|
||||
},
|
||||
|
||||
parseForStuttgart: function (dp) {
|
||||
var arr = XLSX.utils.sheet_to_json(dp, {
|
||||
header: "A",
|
||||
@ -367,28 +437,22 @@ var app = new Vue({
|
||||
time = moment(element.D);
|
||||
art = element.E.trim();
|
||||
name = element.F ? element.F.trim() : "";
|
||||
beschreibung = typeof(element.I) != 'undefined' ? element.I.trim()
|
||||
: typeof(element.J) != 'undefined' ? element.J.trim()
|
||||
: "";
|
||||
}
|
||||
else if (element.hasOwnProperty("G") && element.hasOwnProperty("H"))
|
||||
{
|
||||
beschreibung = typeof (element.I) != 'undefined' ? element.I.trim() :
|
||||
typeof (element.J) != 'undefined' ? element.J.trim() :
|
||||
"";
|
||||
} else if (element.hasOwnProperty("G") && element.hasOwnProperty("H")) {
|
||||
// Vorstellung
|
||||
time = moment(element.G);
|
||||
art = "VS";
|
||||
name = element.H.trim();
|
||||
beschreibung = typeof(element.I) != 'undefined' ? element.I.trim()
|
||||
: typeof(element.J) != 'undefined' ? element.J.trim()
|
||||
: "";
|
||||
}
|
||||
else if (element.hasOwnProperty("I"))
|
||||
{
|
||||
beschreibung = typeof (element.I) != 'undefined' ? element.I.trim() :
|
||||
typeof (element.J) != 'undefined' ? element.J.trim() :
|
||||
"";
|
||||
} else if (element.hasOwnProperty("I")) {
|
||||
// Spielort/Extras
|
||||
beschreibung = element.I.trim();
|
||||
name = name ? name : "Spielort/Extras";
|
||||
}
|
||||
else if (element.hasOwnProperty("J"))
|
||||
{
|
||||
} else if (element.hasOwnProperty("J")) {
|
||||
// Spielort/Extras Fallback
|
||||
beschreibung = element.J.trim();
|
||||
name = name ? name : "Spielort/Extras";
|
||||
@ -472,21 +536,22 @@ var app = new Vue({
|
||||
|
||||
selectShift: function (shift) {
|
||||
this.selectedShift = Shift.thaw(shift);
|
||||
|
||||
this.keepShift = shift;
|
||||
M.updateTextFields();
|
||||
$('#shiftModal').modal('open');
|
||||
this.openModal('shiftModal');
|
||||
},
|
||||
|
||||
saveChanges: function (changedShift) {
|
||||
this.shifts.splice(this.shifts.indexOf(this.keepShift), 1, changedShift);
|
||||
|
||||
$('#shiftModal').modal('close');
|
||||
this.closeModal('shiftModal');
|
||||
this.keepShift = '';
|
||||
this.selectedShift = '';
|
||||
},
|
||||
|
||||
discardChanges: function (changedShift) {
|
||||
$('#shiftModal').modal('close');
|
||||
this.closeModal('shiftModal');
|
||||
this.keepShift = '';
|
||||
this.selectedShift = '';
|
||||
},
|
||||
@ -494,20 +559,28 @@ var app = new Vue({
|
||||
editRule: function (rule) {
|
||||
this.selectedRule = Rule.thaw(rule);
|
||||
this.selectedRuleIndex = this.rules.indexOf(rule);
|
||||
$('#ruleModal').modal('open');
|
||||
this.openModal('ruleModal');
|
||||
},
|
||||
|
||||
saveRule: function () {
|
||||
this.rules[this.selectedRuleIndex] = this.selectedRule;
|
||||
|
||||
$('#ruleModal').modal('close');
|
||||
this.closeModal('ruleModal');
|
||||
this.selectedRule = new Rule();
|
||||
},
|
||||
|
||||
discardRule: function () {
|
||||
$('#ruleModal').modal('close');
|
||||
this.closeModal('ruleModal');
|
||||
|
||||
this.selectedRule = new Rule();
|
||||
},
|
||||
|
||||
applyRules: function () {
|
||||
var shifts = this.shifts;
|
||||
shifts.forEach(function (shift) {
|
||||
Shift.setDurationFromRules(shift, this.rules);
|
||||
});
|
||||
this.shifts = shifts;
|
||||
}
|
||||
|
||||
},
|
||||
@ -517,5 +590,12 @@ var app = new Vue({
|
||||
el.focus();
|
||||
}
|
||||
}
|
||||
},
|
||||
mounted: function () {
|
||||
M.AutoInit();
|
||||
var els = document.querySelectorAll('.timepicker');
|
||||
this.timepickers = M.Timepicker.init(els, this.config.timepicker);
|
||||
var el = document.querySelector(".stepper");
|
||||
this.stepper = new MStepper(el, this.config.stepper);
|
||||
}
|
||||
})
|
||||
|
||||
233
index.html
233
index.html
@ -12,14 +12,16 @@
|
||||
<link rel="mask-icon" href="/favicons/safari-pinned-tab.svg" color="#e6b300">
|
||||
<link rel="stylesheet" href="https://fonts.googleapis.com/icon?family=Material+Icons">
|
||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/materialize/1.0.0/css/materialize.min.css">
|
||||
|
||||
<link rel="stylesheet" href="https://unpkg.com/materialize-stepper@3.1.0/dist/css/mstepper.min.css">
|
||||
<link rel="stylesheet" href="css/page.css">
|
||||
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div id="app">
|
||||
<nav class="nav-extended indigo">
|
||||
<div class="nav-wrapper container ">
|
||||
<nav class="nav blue">
|
||||
<div class="container">
|
||||
<span class="brand-logo">
|
||||
<img src="/img/logo.svg" height="30">
|
||||
Dienstplan Converter
|
||||
@ -28,128 +30,34 @@
|
||||
<link rel="icon" type="image/png" href="/favicons/favicon-16x16.png" sizes="16x16">
|
||||
<link rel="mask-icon" href="/favicons/safari-pinned-tab.svg" color="#e6b300">
|
||||
</span>
|
||||
<a href="#" data-target="mobile-nav" class="sidenav-trigger"><i class="material-icons">menu</i></a>
|
||||
<ul id="nav-mobile" class="right hide-on-med-and-down">
|
||||
<li class=""><a class="active" href="#termine">Termine</a></li>
|
||||
<li class=""><a href="#Einstellungen">Regeln</a></li>
|
||||
</ul>
|
||||
|
||||
</ul>
|
||||
<ul class="tabs tabs-transparent">
|
||||
<li class="tab"><a class="active" href="#termine">Termine</a></li>
|
||||
<li class="tab"><a href="#Einstellungen">Regeln</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
</nav>
|
||||
<ul class="sidenav" id="mobile-nav">
|
||||
|
||||
</ul>
|
||||
<div id="body">
|
||||
<main class="container">
|
||||
<div id="termine">
|
||||
|
||||
<div class="" v-if="shifts.length > 0">
|
||||
<h3 class="title">Termine</h3>
|
||||
<table class="highlight">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Datum</th>
|
||||
<th>Dauer</th>
|
||||
<th>Info</th>
|
||||
<th></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<template v-for="g in groupedTermine">
|
||||
<tr v-for="(s,i) in g">
|
||||
<th v-if="i == 0" :rowspan="g.length">
|
||||
{{s.FormattedDatum}}
|
||||
</th>
|
||||
<td>{{ s.Beginn }} - {{ s.Ende }} Uhr</td>
|
||||
<td>
|
||||
<h6>{{ s.VEventTitle }}</h6>
|
||||
<p v-if="s.Ort!=''">
|
||||
<i class="material-icons red-text">location_on</i>
|
||||
{{ s.Ort }}
|
||||
</p>
|
||||
<blockquote v-if="s.Ort != s.Beschreibung">
|
||||
{{ s.Beschreibung }}
|
||||
</blockquote>
|
||||
</td>
|
||||
<td>
|
||||
<button class="btn-flat" @click="removeShift(s)">löschen</button>
|
||||
<button class="btn-flat" @click="selectShift(s)">bearbeiten</button>
|
||||
</td>
|
||||
</tr>
|
||||
</template>
|
||||
</tbody>
|
||||
</table>
|
||||
<div class="card-action">
|
||||
<button class="btn-flat waves-effect" @click="createDownloadFile"
|
||||
:disabled=" (remaining > 0) ? null : 'disabled'">
|
||||
Kalenderdatei erstellen
|
||||
</button>
|
||||
<a class="btn-flat waves-effect" :href="icsFile" :class="[ icsFile ? '' : 'disabled']"
|
||||
download="dienstplan.ics" @click="downloadFile">
|
||||
Kalenderdatei herunterladen
|
||||
</a>
|
||||
<a class="btn-flat red-text waves-effect" @click="cleanStorage"
|
||||
:disabled=" (remaining > 0) ? null : 'disabled'">
|
||||
Termine löschen
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card" v-else>
|
||||
<div class="card-content center-align" style="height:100px;">
|
||||
<h3 class="card-title">
|
||||
Noch keine Termine da
|
||||
</h3>
|
||||
|
||||
</div>
|
||||
<div class="card-action">
|
||||
<label class="btn-flat waves-effect waves-green" data-position="left"
|
||||
<ul class="stepper">
|
||||
<li class="step active">
|
||||
<div class="step-title waves-effect">Dienstplan-Datei auswählen</div>
|
||||
<div class="step-content">
|
||||
<label class="btn waves-effect waves-green" data-position="left"
|
||||
data-tooltip="Dienstplan einlesen" for="fileInput">
|
||||
Datei auswählen
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="fixed-action-btn">
|
||||
<a class="btn-floating btn-large orange darken-2 waves-effect">
|
||||
<i class="large material-icons">work</i>
|
||||
</a>
|
||||
<ul>
|
||||
<li>
|
||||
<label class="btn-floating green tooltipped" data-position="left"
|
||||
data-tooltip="Dienstplan einlesen" for="fileInput">
|
||||
<i class="material-icons">publish</i>
|
||||
</label>
|
||||
</li>
|
||||
<li>
|
||||
<button class="btn-floating blue tooltipped" data-position="left"
|
||||
data-tooltip="Kalenderdatei erstellen" @click="createDownloadFile"
|
||||
<div class="card-panel" v-if="format">Erkanntes Format: {{format}}</div>
|
||||
<div class="step-actions">
|
||||
<button class="waves-effect waves-dark btn next-step">Weiter</button>
|
||||
|
||||
<a class="btn-flat red-text waves-effect" @click="cleanStorage"
|
||||
:disabled=" (remaining > 0) ? null : 'disabled'">
|
||||
<i class="material-icons">description</i>
|
||||
</button>
|
||||
</li>
|
||||
<li>
|
||||
<a class="btn-floating yellow tooltipped" data-position="left"
|
||||
data-tooltip="Kalenderdatei herunterladen" :href="icsFile"
|
||||
v-bind:class="[ icsFile ? '' : 'disabled']" download="dienstplan.ics"
|
||||
@click="downloadFile">
|
||||
<i class="material-icons">get_app</i>
|
||||
{{ remaining }} Termine löschen
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a class="btn-floating red tooltipped" data-position="left" data-tooltip="Tabelle leeren"
|
||||
@click="cleanStorage" :disabled=" (remaining > 0) ? null : 'disabled'"><i
|
||||
class="material-icons">clear_all</i></a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="" id="Einstellungen">
|
||||
<div class="">
|
||||
<h3 class="title">Regeln für die Dauer</h3>
|
||||
</div>
|
||||
</li>
|
||||
<li class="step">
|
||||
<div class="step-title waves-effect" data-step-label="Termin-Dauer-Bestimmung">
|
||||
Regeln prüfen
|
||||
</div>
|
||||
<div class="step-content">
|
||||
<div>
|
||||
<span class="chip orange">Titel der Veranstaltung</span>
|
||||
<span class="chip indigo">Art des Dienstes</span>
|
||||
@ -176,9 +84,89 @@
|
||||
</div>
|
||||
</a>
|
||||
</div>
|
||||
<div class="step-actions">
|
||||
<button class="waves-effect waves-dark btn-flat" @click.prevent="applyRules">
|
||||
Regeln anwenden
|
||||
</button>
|
||||
<button class="waves-effect waves-dark btn next-step">Weiter</button>
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
<li class="step">
|
||||
<div class="step-title waves-effect">Termine prüfen</div>
|
||||
<div class="step-content">
|
||||
<table class="highlight">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Datum</th>
|
||||
<th>Dauer</th>
|
||||
<th>Info</th>
|
||||
<th></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<template v-for="g in groupedTermine">
|
||||
<tr v-for="(s,i) in g">
|
||||
<th v-if="i == 0" :rowspan="g.length">
|
||||
{{s.FormattedDatum}}
|
||||
</th>
|
||||
<td>
|
||||
<button class="waves-effect waves-light btn-small btn-flat" @click.prevent="updateBeginn(s, -1)" title="1 Stunde früher">
|
||||
<i class="material-icons">skip_previous</i>
|
||||
</button>
|
||||
{{ s.Beginn }} - {{ s.Ende }} Uhr
|
||||
<button class="waves-effect waves-light btn-small btn-flat" @click.prevent="updateBeginn(s, 1)" title="1 Stunde später">
|
||||
<i class="material-icons">skip_next</i>
|
||||
</button>
|
||||
</td>
|
||||
<td>
|
||||
<h6>{{ s.VEventTitle }}</h6>
|
||||
<p v-if="s.Ort!=''">
|
||||
<i class="material-icons red-text">location_on</i>
|
||||
{{ s.Ort }}
|
||||
</p>
|
||||
<blockquote v-if="s.Ort != s.Beschreibung">
|
||||
{{ s.Beschreibung }}
|
||||
</blockquote>
|
||||
</td>
|
||||
<td>
|
||||
<button class="btn-flat"
|
||||
@click.prevent="removeShift(s)">löschen</button>
|
||||
<button class="btn-flat"
|
||||
@click.prevent="selectShift(s)">bearbeiten</button>
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
</template>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<div class="step-actions">
|
||||
<button class="waves-effect waves-dark btn blue" @click.prevent="changeTime(-1)">alle 1 h früher</button>
|
||||
<button class="waves-effect waves-dark btn blue" @click.prevent="changeTime(1)">alle 1 h später</button>
|
||||
<button class="waves-effect waves-dark btn next-step">Weiter</button>
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
<li class="step">
|
||||
<div class="step-title waves-effect">Kalenderdatei speichern</div>
|
||||
<div class="step-content">
|
||||
<p>
|
||||
Erst die Kalenderdatei erstellen. Danach kann sie gespeichert werden.
|
||||
</p>
|
||||
<div class="step-actions">
|
||||
<button class="btn waves-effect" @click.prevent="createDownloadFile"
|
||||
:disabled=" (remaining > 0) ? null : 'disabled'">
|
||||
Kalenderdatei erstellen
|
||||
</button>
|
||||
<a class="btn waves-effect" :href="icsFile" :class="[ icsFile ? '' : 'disabled']"
|
||||
download="dienstplan.ics" @click.stop="downloadFile">
|
||||
Kalenderdatei speichern
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
</main>
|
||||
<div id="confirmModal" class="modal active">
|
||||
<div class="modal-content">
|
||||
@ -189,7 +177,7 @@
|
||||
<button class="btn-flat" @click="false">Abbrechen</button>
|
||||
</div>
|
||||
</div>
|
||||
<div id="ruleModal" class="modal bottom-sheet active">
|
||||
<div id="ruleModal" class="modal modal-fixed-footer active">
|
||||
<div class="modal-content">
|
||||
<h4>Regel anpassen</h4>
|
||||
<div class="row">
|
||||
@ -218,7 +206,7 @@
|
||||
@click="discardRule(selectedRule)">Verwerfen</button>
|
||||
</div>
|
||||
</div>
|
||||
<div id="shiftModal" class="modal bottom-sheet">
|
||||
<div id="shiftModal" class="modal modal-fixed-footer">
|
||||
<div class="modal-content">
|
||||
<h4>{{ selectedShift.VEventTitle || 'kein Titel'}}</h4>
|
||||
<div class="row">
|
||||
@ -231,17 +219,18 @@
|
||||
<label class="active" for="shift_kind">Art</label>
|
||||
</div>
|
||||
<div class="input-field col s6 ">
|
||||
<input id="shift_date" type="date" class="datepicker" v-model="selectedShift.Datum"
|
||||
<input id="shift_date" type="date" class="datepicker" v-model.lazy="selectedShift.Datum"
|
||||
placeholder="Datum">
|
||||
<label class="active" for="shift_date">Datum</label>
|
||||
</div>
|
||||
<div class="input-field col s6">
|
||||
<input id="shift_begin" type="time" v-model="selectedShift.Beginn" placeholder="Uhrzeit"
|
||||
class="timepicker no-autoinit" :data-default="selectedShift.Beginn">
|
||||
<input id="shift_begin" type="time" v-model.lazy="selectedShift.Beginn"
|
||||
placeholder="Uhrzeit" class="timepicker no-autoinit"
|
||||
:data-default="selectedShift.Beginn">
|
||||
<label class="active" for="shift_begin">Anfang</label>
|
||||
</div>
|
||||
<div class="input-field col s6 ">
|
||||
<input id="shift_end" type="time" v-model="selectedShift.Ende" placeholder="Ende"
|
||||
<input id="shift_end" type="time" v-model.lazy="selectedShift.Ende" placeholder="Ende"
|
||||
class="timepicker no-autoinit">
|
||||
<label class="active" for="shift_end">Ende</label>
|
||||
</div>
|
||||
@ -251,7 +240,7 @@
|
||||
<label class="active" for="shift_desc">Beschreibung</label>
|
||||
</div>
|
||||
<div class="input-field col s6 ">
|
||||
<input id="shift_location" type="text" v-model="selectedShift.Ort" placeholder="keine Ort">
|
||||
<input id="shift_location" type="text" v-model="selectedShift.Ort" placeholder="kein Ort">
|
||||
<label class="active" for="shift_location">Ort</label>
|
||||
</div>
|
||||
</div>
|
||||
@ -272,6 +261,8 @@
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.11/lodash.min.js"></script>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/materialize/1.0.0/js/materialize.min.js"></script>
|
||||
|
||||
<script src="https://unpkg.com/materialize-stepper@3.1.0/dist/js/mstepper.min.js"></script>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/xlsx/0.14.1/xlsx.full.min.js"></script>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.23.0/moment-with-locales.min.js"></script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.22/dist/vue.js"></script>
|
||||
|
||||
78
js/shift.js
78
js/shift.js
@ -7,10 +7,17 @@ var TIMEZONE_NAME = "Europe/Berlin";
|
||||
//requires moment.js
|
||||
|
||||
Array.prototype.asChipData = function () {
|
||||
return this.map((e,i) => {return {tag:e,id:i}; })
|
||||
return this.map((e, i) => {
|
||||
return {
|
||||
tag: e,
|
||||
id: i
|
||||
};
|
||||
})
|
||||
}
|
||||
Array.prototype.fromChipData = function () {
|
||||
return this.map(e => {return e.tag; })
|
||||
return this.map(e => {
|
||||
return e.tag;
|
||||
})
|
||||
}
|
||||
|
||||
function Rule() {
|
||||
@ -93,16 +100,48 @@ Rule.thaw = function(json) {
|
||||
}
|
||||
Rule.defaults = function () {
|
||||
var rules = [];
|
||||
var input = [
|
||||
{name: "EF #01", dauer: 60, arten: ['VS'], titel: ['Kinderkonzert']},
|
||||
{name: "EF #02", dauer: 120, arten: ['VS'], titel: ["Expeditionskonzert", "Sinfoniekonzert"]},
|
||||
{name: "EF #03", dauer: 150, arten: ['Oa', 'GP'], titel: ['Expeditionskonzert']},
|
||||
{name: "EF #04", dauer: 60, arten: ['Oa', 'GP'], titel: ['Expeditionskonzert']},
|
||||
{name: "EF #05", dauer: 150, arten: ['Oa', 'OSP']},
|
||||
{name: "EF #06", dauer: 180, arten: ["VS", "BO", "OHP", "HP", "GP", "Prem", "WA"]},
|
||||
{name: "Standard", dauer: 60}
|
||||
var input = [{
|
||||
name: "EF #01",
|
||||
dauer: 60,
|
||||
arten: ['VS'],
|
||||
titel: ['Kinderkonzert']
|
||||
},
|
||||
{
|
||||
name: "EF #02",
|
||||
dauer: 120,
|
||||
arten: ['VS'],
|
||||
titel: ["Expeditionskonzert", "Sinfoniekonzert"]
|
||||
},
|
||||
{
|
||||
name: "EF #03",
|
||||
dauer: 150,
|
||||
arten: ['Oa', 'GP'],
|
||||
titel: ['Expeditionskonzert']
|
||||
},
|
||||
{
|
||||
name: "EF #04",
|
||||
dauer: 60,
|
||||
arten: ['Oa', 'GP'],
|
||||
titel: ['Expeditionskonzert']
|
||||
},
|
||||
{
|
||||
name: "EF #05",
|
||||
dauer: 150,
|
||||
arten: ['Oa', 'OSP']
|
||||
},
|
||||
{
|
||||
name: "EF #06",
|
||||
dauer: 180,
|
||||
arten: ["VS", "BO", "OHP", "HP", "GP", "Prem", "WA"]
|
||||
},
|
||||
{
|
||||
name: "Standard",
|
||||
dauer: 60
|
||||
}
|
||||
];
|
||||
input.forEach(e => { rules.push(new Rule(e)); });
|
||||
input.forEach(e => {
|
||||
rules.push(new Rule(e));
|
||||
});
|
||||
|
||||
return rules;
|
||||
}
|
||||
@ -135,7 +174,7 @@ function Shift() {
|
||||
this.Ende = options.ende;
|
||||
} else {
|
||||
if (!options.dontSetDurationFromRules) {
|
||||
Shift.setDurationFromRules(this);
|
||||
Shift.setDurationFromRules(this, DURATION_RULES);
|
||||
}
|
||||
}
|
||||
|
||||
@ -173,7 +212,8 @@ Shift.prototype = {
|
||||
this._begin = dateMoment.clone();
|
||||
},
|
||||
get Ende() {
|
||||
return this._begin.clone().add(this._duration).format(TIME_FORMAT);
|
||||
var ende = this._begin.clone().add(this._duration).format(TIME_FORMAT);
|
||||
return ende;
|
||||
},
|
||||
set Ende(value) {
|
||||
var dateMoment = moment(this.Datum + " " + value, DATE_INPUT_FORMAT + " " + TIME_FORMAT);
|
||||
@ -227,7 +267,7 @@ Shift.prototype = {
|
||||
}
|
||||
|
||||
}
|
||||
Shift.setDurationFromRules = function (shift) {
|
||||
Shift.setDurationFromRules = function (shift, rules) {
|
||||
'use strict';
|
||||
var isAllDayEvent = shift.Beginn == "00:00";
|
||||
if (isAllDayEvent) {
|
||||
@ -237,8 +277,8 @@ Shift.setDurationFromRules = function (shift) {
|
||||
var art = shift.Art.toLowerCase();
|
||||
var titel = shift.Name.toLowerCase();
|
||||
var duration = 60;
|
||||
for (var rIndex in DURATION_RULES) {
|
||||
var rule = DURATION_RULES[rIndex];
|
||||
for (var rIndex in rules) {
|
||||
var rule = rules[rIndex];
|
||||
|
||||
if (rule.fits(art, titel)) {
|
||||
duration = rule.Dauer;
|
||||
@ -260,8 +300,7 @@ Shift.prototype.toVEvent = function () {
|
||||
Shift.thaw = function (jsonShift) {
|
||||
moment.locale(MOMENT_LOCALE);
|
||||
var begin = moment(jsonShift._begin);
|
||||
var shift = new Shift(
|
||||
{
|
||||
var shift = new Shift({
|
||||
art: jsonShift._kind,
|
||||
name: jsonShift._name,
|
||||
datum: begin,
|
||||
@ -273,3 +312,6 @@ Shift.thaw = function (jsonShift) {
|
||||
shift.Dauer = moment.duration(jsonShift._duration);
|
||||
return shift;
|
||||
};
|
||||
Shift.prototype.updateBeginn = function(hour) {
|
||||
this._begin = this._begin.add('hours', hour);
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user