324 lines
15 KiB
HTML
324 lines
15 KiB
HTML
<!DOCTYPE html>
|
|
<html xmlns:th="http://www.thymeleaf.org" xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"
|
|
xmlns:sec="http://www.thymeleaf.org/extras/spring-security" layout:decorate="~{layout/main.html}">
|
|
<head>
|
|
<title>Arbeitszeit</title>
|
|
</head>
|
|
<body>
|
|
<font layout:fragment="title">Arbeitszeit</font>
|
|
<ul layout:fragment="menuitem">
|
|
<li class="nav-item" sec:authorize="hasRole('timetrack_user')">
|
|
<a class="nav-link btn btn-primary btn-white-text" th:href="@{/done/list/previousday}" style="width: 50px; float: left;"><i class="fa fa-chevron-left"></i></a>
|
|
<form th:action="@{/done/list}" th:object="${doneModel}" method="post" style="float:left;">
|
|
<div class="nav-link" style="padding-top: 5px !important; padding-bottom: 0px !important">
|
|
<div class="input-group input-group-sm mb-3" style="margin-bottom: 0px !important">
|
|
<input type="date" class="form-control" th:value="*{day}" th:field="*{day}" />
|
|
<button type="submit" class="btn btn-primary btn-sm">Ok</button>
|
|
</div>
|
|
</div>
|
|
</form>
|
|
<a class="nav-link btn btn-primary btn-white-text" th:href="@{/done/list/nextday}" style="width: 50px; float: left;"><i class="fa fa-chevron-right"></i></a>
|
|
</li>
|
|
</ul>
|
|
<ul layout:fragment="menu">
|
|
<li class="nav-item" sec:authorize="hasRole('timetrack_user')">
|
|
<table>
|
|
<tr>
|
|
<td><a class="nav-link btn btn-success btn-white-text" th:href="@{/done/add/{day}(day=${doneModel.day})}">Neuer
|
|
Eintrag</a></td>
|
|
<td>
|
|
<div class="dropdown">
|
|
<button class="btn btn-white-text dropdown-toggle" type="button" data-bs-toggle="dropdown" aria-expanded="false">
|
|
Letzte Einträge
|
|
</button>
|
|
<ul class="dropdown-menu">
|
|
<li th:each="recent : ${recentList}">
|
|
<a class="dropdown-item" th:href="@{/done/addrecent/{id}(id=${recent.pk})}"
|
|
th:text="${(recent.getJobName()!=null?recent.getJobName():'') + '@' + (recent.getProject()!=null?recent.getProject().getName():'') + (recent.getModule()!=null? ', ' + recent.getModule().getName() : '')}"></a>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
</td>
|
|
<td style="padding-left: 8px"><a class="nav-link btn-list" th:href="@{/done/list}"><i class="fas fa-sync"></i></a></td>
|
|
</tr>
|
|
</table>
|
|
</li>
|
|
</ul>
|
|
<main layout:fragment="content">
|
|
<ul class="nav nav-tabs navback" role="tablist">
|
|
<li class="nav-item"><a class="nav-link navlinkstyle active" data-bs-toggle="tab" href="#div_list">Liste</a></li>
|
|
<li class="nav-item"><a class="nav-link navlinkstyle" data-bs-toggle="tab" href="#div_schedule">Kalender</a></li>
|
|
<li class="nav-item"><a class="nav-link navlinkstyle" data-bs-toggle="tab" href="#div_project">Projekt</a></li>
|
|
<li class="nav-item"><a class="nav-link navlinkstyle" data-bs-toggle="tab" href="#div_module">Modul</a></li>
|
|
<li class="nav-item"><a class="nav-link navlinkstyle" data-bs-toggle="tab" href="#div_job">Aufgabe</a></li>
|
|
<li class="nav-item"><a class="nav-link navlinkstyle" data-bs-toggle="tab" href="#div_billing">Abrechnung</a></li>
|
|
<li class="nav-item"><a class="nav-link navlinkstyle" data-bs-toggle="tab" href="#div_overtime">Überstunden</a></li>
|
|
<li class="nav-item"><a class="nav-link navlinkstyle" data-bs-toggle="tab" href="#div_slot">Slots</a></li>
|
|
</ul>
|
|
<div class="tabdivblurred tab-content">
|
|
<div id="div_list" class="tab-pane active tab-pane-table">
|
|
<table class="table table-striped table-condensed">
|
|
<thead>
|
|
<tr>
|
|
<th>Zeit</th>
|
|
<th>Dauer</th>
|
|
<th>Projekt</th>
|
|
<th>Modul</th>
|
|
<th>Aufgabe</th>
|
|
<th>Abrechnung</th>
|
|
<th>
|
|
<div class="dropdown">
|
|
<button class="btn btn-outline-secondary dropdown-toggle" type="button" data-bs-toggle="dropdown" aria-expanded="false">Favoriten</button>
|
|
<ul class="dropdown-menu">
|
|
<li th:each="f : ${favorites}">
|
|
<a class="dropdown-item" th:href="@{/done/usefav/{id}(id=${f.fkFavorite})}"><span th:text="${f.project} + ' ' + ${f.module} + ' ' + ${f.job}"></span></a>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
<tr th:each="done : ${doneList}">
|
|
<td><a class="hoverlink" th:href="@{/done/edit/{id}(id=${done.pk})}"><span th:text="${done.timeNote}"></span></a>
|
|
<a th:if="${done.timeUntil == null}" style="margin-left: 4px" class="btn-list" th:href="@{/done/end/{id}(id=${done.pk})}" title="aktuelle Uhrzeit setzen"><i class="fa fa-clock"></i></a>
|
|
</td>
|
|
<td><a class="hoverlink" th:href="@{/done/edit/{id}(id=${done.pk})}"><span th:text="${done.timeDiff}"></span></a></td>
|
|
<td><a class="hoverlink" th:href="@{/done/edit/{id}(id=${done.pk})}"><span class="boldtext"
|
|
th:text="${done.project?.name}"></span></a></td>
|
|
<td><a class="hoverlink" th:href="@{/done/edit/{id}(id=${done.pk})}"><span class="boldtext"
|
|
th:text="${done.module?.name}"></span></a></td>
|
|
<td><a class="hoverlink" th:href="@{/done/edit/{id}(id=${done.pk})}"><span class="boldtext"
|
|
th:text="${done.activity?.name}"></span></a></td>
|
|
<td><span th:text="${done.billing.shortcut}" th:class="'billing ' + ${done.billing.csskey}"
|
|
th:if="${done.billing != null}"></span></td>
|
|
<td>
|
|
<a class="btn-list" th:href="@{/done/copy/{id}(id=${done.pk})}" title="Aufgabe neu beginnen"><i class="fa fa-copy"></i></a>
|
|
<a class="btn-list" th:href="@{/done/edit/{id}(id=${done.pk})}" title="Eintrag bearbeiten"><i class="fa fa-edit"></i></a>
|
|
<a class="btn-list" th:href="@{/done/favorize/{id}(id=${done.pk})}" title="als Favorit speichern" th:if="${!done.isFavorite}"><i class="far fa-star golden"></i></a>
|
|
<a class="btn-list" th:href="@{/done/unfavorize/{id}(id=${done.pk})}" title="Favoritenstatus entfernen" th:if="${done.isFavorite}"><i class="fas fa-star golden"></i></a>
|
|
</td>
|
|
</tr>
|
|
</tbody>
|
|
<tfoot>
|
|
<tr th:if="${daysum}">
|
|
<td>Start: <span class="emphgreen" th:text="${#temporals.format(daysum.daytimeFrom, 'HH:mm')}" th:if="${daysum.daytimeFrom}"></span></td>
|
|
<td>Ende: <span class="emphgreen" th:text="${#temporals.format(daysum.daytimeUntil, 'HH:mm')}" th:if="${daysum.daytimeUntil}"></span></td>
|
|
<td>Arbeitszeit total: <span class="emphblue" th:text="${#temporals.format(daysum.dayworktime, 'HH:mm')}" th:if="${daysum.dayworktime}"></span></td>
|
|
<td>Pausezeit total: <span class="emphorange" th:text="${#temporals.format(daysum.breaks, 'HH:mm')}" th:if="${daysum.breaks}"></span></td>
|
|
<td>Überstunden heute: <span class="emphred" th:text="${daysum.printDayOvertime()}"></span></td>
|
|
<td colspan="2">Überstunden total: <span class="emphpink" th:text="${daysum.printTotalOvertime()}" th:if="${daysum.totalOvertime}"></span></td>
|
|
</tr>
|
|
<tr>
|
|
<td></td>
|
|
<td><span th:if="${sum.getBillingTime('WP2') != '0,0 h'}"><span class="billing WP2">WP2</span><span
|
|
th:text="${sum.getBillingTime('WP2')}" class="distfat"></span></span></td>
|
|
<td><span th:if="${sum.getBillingTime('WP4') != '0,0 h'}"><span class="billing WP4">WP4</span><span
|
|
th:text="${sum.getBillingTime('WP4')}" class="distfat"></span></span></td>
|
|
<td><span th:if="${sum.getBillingTime('WP5') != '0,0 h'}"><span class="billing WP5">WP5</span><span
|
|
th:text="${sum.getBillingTime('WP5')}" class="distfat"></span></span></td>
|
|
<td><span th:if="${sum.getBillingTime('TA3') != '0,0 h'}"><span class="billing TA3">TA3</span><span
|
|
th:text="${sum.getBillingTime('TA3')}" class="distfat"></span></span></td>
|
|
<td colspan="2"><span class="billing">X</span><span th:text="${sum.getBillingTime(null)}" class="distfat"></span></td>
|
|
</tr>
|
|
</tfoot>
|
|
</table>
|
|
</div>
|
|
<div id="div_schedule" class="tab-pane fade tab-pane-table">
|
|
<div id="schedule" class="schedule"></div>
|
|
</div>
|
|
<div id="div_project" class="tab-pane fade tab-pane-table">
|
|
<table id="project_table" class="table table-striped table-condensed">
|
|
<thead>
|
|
<tr>
|
|
<th>Name</th>
|
|
<th>Benutzt in %</th>
|
|
<th></th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
<tr th:each="project : ${projectList}">
|
|
<td><span th:text="${project.name}"></span></td>
|
|
<td><span th:text="${project.percentUsage}"></span></td>
|
|
<td><a th:href="@{/done/edit/project/{id}(id=${project.pk})}" th:title="${project.pk}"><i class="fa fa-edit"></i></a></td>
|
|
</tr>
|
|
</tbody>
|
|
<tfoot>
|
|
<tr>
|
|
<td colspan="3"><a class="nav-link btn btn-success btn-white-text" th:href="@{/done/add/project}">neues Projekt</a>
|
|
</td>
|
|
</tr>
|
|
</tfoot>
|
|
</table>
|
|
</div>
|
|
<div id="div_module" class="tab-pane fade tab-pane-table">
|
|
<table id="module_table" class="table table-striped table-condensed">
|
|
<thead>
|
|
<tr>
|
|
<th>Name</th>
|
|
<th>Benutzt in %</th>
|
|
<th></th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
<tr th:each="module : ${moduleList}">
|
|
<td><span th:text="${module.name}"></span></td>
|
|
<td><span th:text="${module.percentUsage}"></span></td>
|
|
<td><a th:href="@{/done/edit/module/{id}(id=${module.pk})}" th:title="${module.pk}"><i class="fa fa-edit"></i></a></td>
|
|
</tr>
|
|
</tbody>
|
|
<tfoot>
|
|
<tr>
|
|
<td colspan="3"><a class="nav-link btn btn-success btn-white-text" th:href="@{/done/add/module}">neues Modul</a></td>
|
|
</tr>
|
|
</tfoot>
|
|
</table>
|
|
</div>
|
|
<div id="div_job" class="tab-pane fade tab-pane-table">
|
|
<table id="job_table" class="table table-striped table-condensed">
|
|
<thead>
|
|
<tr>
|
|
<th>Name</th>
|
|
<th>Benutzt in %</th>
|
|
<th></th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
<tr th:each="job : ${jobList}">
|
|
<td><span th:text="${job.name}"></span></td>
|
|
<td><span th:text="${job.percentUsage}"></span></td>
|
|
<td><a th:href="@{/done/edit/job/{id}(id=${job.pk})}" th:title="${job.pk}"><i class="fa fa-edit"></i></a></td>
|
|
</tr>
|
|
</tbody>
|
|
<tfoot>
|
|
<tr>
|
|
<td colspan="3"><a class="nav-link btn btn-success btn-white-text" th:href="@{/done/add/job}">neue Aufgabe</a></td>
|
|
</tr>
|
|
</tfoot>
|
|
</table>
|
|
</div>
|
|
<div id="div_billing" class="tab-pane fade tab-pane-table">
|
|
<table id="billing_table" class="table table-striped table-condensed">
|
|
<thead>
|
|
<tr>
|
|
<th>Name</th>
|
|
<th>Symbol</th>
|
|
<th>Benutzt in %</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
<tr th:each="billing : ${billingList}">
|
|
<td><span th:text="${billing.name}"></span></td>
|
|
<td><span th:text="${billing.shortcut}" th:class="'billing ' + ${billing.csskey}"></span></td>
|
|
<td><span th:text="${billing.percentUsage}"></span></td>
|
|
</tr>
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
<div id="div_overtime" class="tab-pane fade tab-pane-table">
|
|
<form th:action="@{/done/overtime/update}" method="post" th:object="${overtimeBean}">
|
|
<input type="hidden" th:field="*{id}" />
|
|
<div class="container">
|
|
<div class="row g-3">
|
|
<div class="col-sm-12">
|
|
<div class="alert alert-info">Hier werden die Überstunden einmalig angegeben. Dabei wird für einen bestimmten Tagesbeginn, an dem die Überstunden bekannt sind, der Wert gesetzt. Alle
|
|
nachfolgenden Zeiten werden bei der Anzeige der Überstunden während der Datenerfassung berücksichtigt und einberechnet.</div>
|
|
</div>
|
|
<div class="col-sm-3">Tagesbeginn</div>
|
|
<div class="col-sm-9">
|
|
<input type="date" th:field="*{impact}" class="form-control" />
|
|
</div>
|
|
<div class="col-sm-3">Überstunden (min)</div>
|
|
<div class="col-sm-9">
|
|
<input type="number" th:field="*{overtimeMinutes}" class="form-control" />
|
|
</div>
|
|
<div class="col-sm-3"></div>
|
|
<div class="col-sm-9">
|
|
<button type="submit" class="btn btn-outline-primary">Übernehmen</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</form>
|
|
</div>
|
|
<div id="div_slot" class="tab-pane fade tab-pane-table">
|
|
<div class="alert alert-info">
|
|
Zur Berechnung der täglichen Überstunden müssen Slots angelegt werden, die definieren, an welchen Tagen wieviele Stunden zu arbeiten ist.
|
|
Die Überstundenberechnung hängt von der Vollständigkeit der vorhandenen Slots ab; fehlen Slots, wird die Arbeitszeit jener Tage nicht eingerechnet.<br />
|
|
Hier werden nur die Slots für diesen Monat angezeigt.
|
|
</div>
|
|
<div class="container">
|
|
<div class="row row-weekday">
|
|
<div class="col">Sonntag</div>
|
|
<div class="col">Montag</div>
|
|
<div class="col">Dienstag</div>
|
|
<div class="col">Mittwoch</div>
|
|
<div class="col">Donnerstag</div>
|
|
<div class="col">Freitag</div>
|
|
<div class="col">Samstag</div>
|
|
</div>
|
|
<div class="row row-weekday">
|
|
<div class="col slot_badge" th:each="o : ${slotOffset}"></div>
|
|
<div class="col slot_badge" th:each="s : ${slots}">
|
|
<span class="slot_badge_left" th:text="${#temporals.format(s.day, 'dd.MM.')}">
|
|
</span><a th:href="@{/done/slot/{id}(id=${s.id})}" class="slot_badge_middle" th:if="${s.id}">
|
|
<i class="fas fa-pencil"></i>
|
|
</a><a th:href="@{/done/slot/add?day=${d}(d=${s.day})}" class="slot_badge_middle" th:unless="${s.id}">
|
|
<i class="fas fa-plus"></i>
|
|
</a>
|
|
<span class="slot_badge_right boldy" th:text="${s.printTime()}" th:if="${s.id}"></span>
|
|
<span class="slot_badge_right" th:unless="${s.id}"> --:-- </span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<script type="text/javascript">
|
|
$(document).ready(function() {
|
|
let width = parseInt($("#schedule").css("min-width"));
|
|
let height = parseInt($("#schedule").css("min-height"));
|
|
var schedule = new Schedule("#schedule", width, height);
|
|
var ctx = $("#scheduleCanvas")[0].getContext("2d");
|
|
var currentDayRecords = JSON.parse('[(${schedule})]');
|
|
var scheduleRecords = currentDayRecords.schedule;
|
|
for (var i = 0; i < scheduleRecords.length; i++) {
|
|
var r = scheduleRecords[i];
|
|
var cssClass = r.billing;
|
|
var color = "#ffffff";
|
|
if (cssClass == "WP5") {
|
|
color = "#aa0000";
|
|
} else if (cssClass == "WP4") {
|
|
color = "#0000aa";
|
|
} else if (cssClass == "WP2") {
|
|
color = "#aaaa00";
|
|
} else if (cssClass == "TA3") {
|
|
color = "#00aa00";
|
|
}
|
|
/* daySlot 7 = sunday, but this should be slot 0 */
|
|
schedule.drawSlot(ctx, r.daySlot > 6 ? 0 : r.daySlot, r.from, r.until, "black", color);
|
|
}
|
|
var localeUrl = '[[@{/js/dataTables/de.json}]]';
|
|
$("#project_table").DataTable({
|
|
"language" : {
|
|
"url" : localeUrl
|
|
}
|
|
});
|
|
$("#module_table").DataTable({
|
|
"language" : {
|
|
"url" : localeUrl
|
|
}
|
|
});
|
|
$("#job_table").DataTable({
|
|
"language" : {
|
|
"url" : localeUrl
|
|
}
|
|
});
|
|
$("#billing_table").DataTable({
|
|
"language" : {
|
|
"url" : localeUrl
|
|
}
|
|
});
|
|
});
|
|
</script>
|
|
</main>
|
|
</body>
|
|
</html> |