further processing

This commit is contained in:
Jörg Henke
2022-07-01 18:13:18 +02:00
parent 05d99cc748
commit 98b3f9d804
10 changed files with 223 additions and 31 deletions

View File

@ -1,2 +1,13 @@
arguments=
auto.sync=false
build.scans.enabled=false
connection.gradle.distribution=GRADLE_DISTRIBUTION(WRAPPER)
connection.project.dir=
eclipse.preferences.version=1
gradle.user.home=
java.home=
jvm.arguments=
offline.mode=false
override.workspace.settings=false
show.console.view=false
show.executions.view=false

View File

@ -106,6 +106,24 @@ public class DoneBean implements Serializable, Comparable<DoneBean> {
return o == null || timeFrom == null || o.getTimeFrom() == null ? 0 : timeFrom.compareTo(o.getTimeFrom());
}
public String getTimeNote() {
LocalDateTime earlier = timeFrom != null ? timeFrom : LocalDateTime.now();
LocalDateTime later = timeUntil != null ? timeUntil : LocalDateTime.now();
StringBuilder buf = new StringBuilder();
if (timeFrom == null) {
buf.append(" ");
} else {
buf.append(String.format("%02d:%02d", earlier.getHour(), earlier.getMinute() % 60));
}
buf.append(" - ");
if (timeUntil == null) {
buf.append(" ");
} else {
buf.append(String.format("%02d:%02d", later.getHour(), later.getMinute() % 60));
}
return buf.toString();
}
public String getTimeDiff() {
LocalDateTime earlier = timeFrom != null ? timeFrom : LocalDateTime.now();
LocalDateTime later = timeUntil != null ? timeUntil : LocalDateTime.now();

View File

@ -42,6 +42,7 @@ public class DoneController {
List<DoneBean> list = doneService.getList(doneModel.getDay(), username);
model.addAttribute("doneList", list);
model.addAttribute("doneModel", doneModel);
model.addAttribute("sum", new SummaryBean(list));
model.addAttribute("projectList", doneService.getProjects());
model.addAttribute("moduleList", doneService.getModules());
model.addAttribute("jobList", doneService.getJobs());

View File

@ -0,0 +1,69 @@
package de.jottyfan.timetrack.spring.done;
import java.io.Serializable;
import java.time.LocalDateTime;
import java.util.List;
/**
*
* @author henkej
*
*/
public class SummaryBean implements Serializable {
private static final long serialVersionUID = 1L;
private final List<DoneBean> list;
public SummaryBean(List<DoneBean> list) {
this.list = list;
}
/**
* @return the start
*/
public String getStart() {
LocalDateTime found = LocalDateTime.now();
for (DoneBean bean : list) {
LocalDateTime ldt = bean.getTimeFrom();
if (ldt != null && ldt.isBefore(found)) {
found = ldt;
}
}
return String.format("%02d:%02d", found.getHour(), found.getMinute() % 60);
}
/**
* @return the end
*/
public String getEnd() {
LocalDateTime found = LocalDateTime.now();
for (DoneBean bean : list) {
LocalDateTime ldt = bean.getTimeUntil();
if (ldt != null && found.isBefore(ldt)) {
found = ldt;
}
}
return String.format("%02d:%02d", found.getHour(), found.getMinute() % 60);
}
/**
* @return the total
*/
public String getTotal() {
return "TODO";
}
/**
* @return the pause
*/
public String getPause() {
return "TODO";
}
/**
* @return the overdue
*/
public String getOverdue() {
return "TODO";
}
}

View File

@ -68,53 +68,81 @@ public class DoneGateway {
/**
* get all projects from the database
*
* @param includeNull if true, add a null value at the beginning of the result
*
* @return a list of found projects
*
* @throws DataAccessException
* @throws ClassNotFoundException
* @throws SQLException
*/
public List<TProjectRecord> getAllProjects() throws DataAccessException, ClassNotFoundException, SQLException {
return getJooq().selectFrom(T_PROJECT).orderBy(T_PROJECT.NAME).fetchInto(TProjectRecord.class);
public List<TProjectRecord> getAllProjects(boolean includeNull) throws DataAccessException, ClassNotFoundException, SQLException {
List<TProjectRecord> list = new ArrayList<>();
if (includeNull) {
list.add(new TProjectRecord(null, null, "---"));
}
list.addAll(getJooq().selectFrom(T_PROJECT).orderBy(T_PROJECT.NAME).fetchInto(TProjectRecord.class));
return list;
}
/**
* get all modules from the database
*
* @param includeNull if true, add a null value at the beginning of the result
*
* @return a list of found modules
*
* @throws DataAccessException
* @throws ClassNotFoundException
* @throws SQLException
*/
public List<TModuleRecord> getAllModules() throws DataAccessException, ClassNotFoundException, SQLException {
return getJooq().selectFrom(T_MODULE).orderBy(T_MODULE.NAME).fetchInto(TModuleRecord.class);
public List<TModuleRecord> getAllModules(boolean includeNull) throws DataAccessException, ClassNotFoundException, SQLException {
List<TModuleRecord> list = new ArrayList<>();
if (includeNull) {
list.add(new TModuleRecord(null, null, "---"));
}
list.addAll(getJooq().selectFrom(T_MODULE).orderBy(T_MODULE.NAME).fetchInto(TModuleRecord.class));
return list;
}
/**
* get all jobs from the database
*
* @param includeNull if true, add a null value at the beginning of the result
*
* @return a list of found jobs
*
* @throws DataAccessException
* @throws ClassNotFoundException
* @throws SQLException
*/
public List<TJobRecord> getAllJobs() throws DataAccessException, ClassNotFoundException, SQLException {
return getJooq().selectFrom(T_JOB).orderBy(T_JOB.NAME).fetchInto(TJobRecord.class);
public List<TJobRecord> getAllJobs(boolean includeNull) throws DataAccessException, ClassNotFoundException, SQLException {
List<TJobRecord> list = new ArrayList<>();
if (includeNull) {
list.add(new TJobRecord(null, null, "---"));
}
list.addAll(getJooq().selectFrom(T_JOB).orderBy(T_JOB.NAME).fetchInto(TJobRecord.class));
return list;
}
/**
* get all billings from the database
*
* @param includeNull if true, add a null value at the beginning of the result
*
* @return a list of found billings
*
* @throws DataAccessException
* @throws ClassNotFoundException
* @throws SQLException
*/
public List<TBillingRecord> getAllBillings() throws DataAccessException, ClassNotFoundException, SQLException {
return getJooq().selectFrom(T_BILLING).orderBy(T_BILLING.NAME).fetchInto(TBillingRecord.class);
public List<TBillingRecord> getAllBillings(boolean includeNull) throws DataAccessException, ClassNotFoundException, SQLException {
List<TBillingRecord> list = new ArrayList<>();
if (includeNull) {
list.add(new TBillingRecord(null, null, "---", null, null));
}
list.addAll(getJooq().selectFrom(T_BILLING).orderBy(T_BILLING.NAME).fetchInto(TBillingRecord.class));
return list;
}
/**
@ -128,7 +156,7 @@ public class DoneGateway {
private Map<Integer, TProjectRecord> getProjectMap()
throws DataAccessException, ClassNotFoundException, SQLException {
Map<Integer, TProjectRecord> map = new HashMap<>();
for (TProjectRecord r : getAllProjects()) {
for (TProjectRecord r : getAllProjects(false)) {
map.put(r.getPk(), r);
}
return map;
@ -144,7 +172,7 @@ public class DoneGateway {
*/
private Map<Integer, TModuleRecord> getModuleMap() throws DataAccessException, ClassNotFoundException, SQLException {
Map<Integer, TModuleRecord> map = new HashMap<>();
for (TModuleRecord r : getAllModules()) {
for (TModuleRecord r : getAllModules(false)) {
map.put(r.getPk(), r);
}
return map;
@ -160,7 +188,7 @@ public class DoneGateway {
*/
private Map<Integer, TJobRecord> getJobMap() throws DataAccessException, ClassNotFoundException, SQLException {
Map<Integer, TJobRecord> map = new HashMap<>();
for (TJobRecord r : getAllJobs()) {
for (TJobRecord r : getAllJobs(false)) {
map.put(r.getPk(), r);
}
return map;
@ -177,7 +205,7 @@ public class DoneGateway {
private Map<Integer, TBillingRecord> getBillingMap()
throws DataAccessException, ClassNotFoundException, SQLException {
Map<Integer, TBillingRecord> map = new HashMap<>();
for (TBillingRecord r : getAllBillings()) {
for (TBillingRecord r : getAllBillings(false)) {
map.put(r.getPk(), r);
}
return map;
@ -207,8 +235,8 @@ public class DoneGateway {
T_DONE.FK_JOB,
T_DONE.FK_BILLING)
.from(T_DONE)
.where(T_DONE.TIME_FROM.between(dayStart, dayEnd))
.and(T_DONE.TIME_UNTIL.between(dayStart, dayEnd))
.where(T_DONE.TIME_FROM.between(dayStart, dayEnd).or(T_DONE.TIME_FROM.isNull()))
.and(T_DONE.TIME_UNTIL.between(dayStart, dayEnd).or(T_DONE.TIME_UNTIL.isNull()))
.and(T_DONE.FK_LOGIN.eq(userId == null ? -999999 : userId));
// @formatter:on
LOGGER.debug("{}", sql.toString());

View File

@ -70,7 +70,7 @@ public class DoneService implements IDoneService {
@Override
public List<TProjectRecord> getProjects() {
try {
return new DoneGateway(dsl).getAllProjects();
return new DoneGateway(dsl).getAllProjects(true);
} catch (Exception e) {
LOGGER.error(e);
return new ArrayList<>();
@ -80,7 +80,7 @@ public class DoneService implements IDoneService {
@Override
public List<TModuleRecord> getModules() {
try {
return new DoneGateway(dsl).getAllModules();
return new DoneGateway(dsl).getAllModules(true);
} catch (Exception e) {
LOGGER.error(e);
return new ArrayList<>();
@ -90,7 +90,7 @@ public class DoneService implements IDoneService {
@Override
public List<TJobRecord> getJobs() {
try {
return new DoneGateway(dsl).getAllJobs();
return new DoneGateway(dsl).getAllJobs(true);
} catch (Exception e) {
LOGGER.error(e);
return new ArrayList<>();
@ -100,7 +100,7 @@ public class DoneService implements IDoneService {
@Override
public List<TBillingRecord> getBillings() {
try {
return new DoneGateway(dsl).getAllBillings();
return new DoneGateway(dsl).getAllBillings(true);
} catch (Exception e) {
LOGGER.error(e);
return new ArrayList<>();

View File

@ -163,3 +163,57 @@ body {
.fc-content {
cursor: pointer;
}
.btn-white-text {
color: white !important;
font-weight: bolder;
}
.hoverlink {
text-decoration: none;
color: black;
}
.hoverlink:hover {
color: #1a5f64;
}
.boldtext {
font-weight: bolder;
}
.emphgreen {
font-weight: bolder;
color: #136600;
border: 1px solid gray;
border-radius: 8px;
background-image: linear-gradient(to left, #e6e6e6, white);
padding: 4px;
}
.emphblue {
font-weight: bolder;
color: #1a5fb4;
border: 1px solid gray;
border-radius: 8px;
background-image: linear-gradient(to left, #e6e6e6, white);
padding: 4px;
}
.emphorange {
font-weight: bolder;
color: #c64600;
border: 1px solid gray;
border-radius: 8px;
background-image: linear-gradient(to left, #e6e6e6, white);
padding: 4px;
}
.emphred {
font-weight: bolder;
color: #a51d2d;
border: 1px solid gray;
border-radius: 8px;
background-image: linear-gradient(to left, #e6e6e6, white);
padding: 4px;
}

View File

@ -7,7 +7,7 @@
<body>
<font layout:fragment="title">Kontakte</font>
<ul layout:fragment="menu">
<li class="nav-item" sec:authorize="hasRole('timetrack_user')"><a class="nav-link" th:href="@{/contact/add}">Neuen
<li class="nav-item" sec:authorize="hasRole('timetrack_user')"><a class="nav-link btn btn-success btn-white-text" th:href="@{/contact/add}">Neuen
Kontakt anlegen</a></li>
</ul>
<main layout:fragment="content">

View File

@ -9,7 +9,7 @@
<ul layout:fragment="menuitem">
<li class="nav-item" sec:authorize="hasRole('timetrack_user')">
<form th:action="@{/done/list}" th:object="${doneModel}" method="post">
<div class="nav-link" style="padding-top: 0px !important">
<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>
@ -19,7 +19,7 @@
</li>
</ul>
<ul layout:fragment="menu">
<li class="nav-item" sec:authorize="hasRole('timetrack_user')"><a class="nav-link" th:href="@{/done/add}">Neuer
<li class="nav-item" sec:authorize="hasRole('timetrack_user')"><a class="nav-link btn btn-success btn-white-text" th:href="@{/done/add}">Neuer
Eintrag</a></li>
</ul>
<main layout:fragment="content">
@ -38,25 +38,36 @@
<table class="table table-striped table-condensed">
<thead>
<tr>
<th>Von</th>
<th>Bis</th>
<th>Zeit</th>
<th>Projekt</th>
<th>Modul</th>
<th>Aufgabe</th>
<th>Abrechnung</th>
<th>Dauer</th>
<th></th>
</tr>
</thead>
<tbody>
<tr th:each="done : ${doneList}">
<td><a th:href="@{/done/edit/{id}(id=${done.pk})}"><span th:text="${#temporals.format(done.timeFrom, 'HH:mm')}"></span></a></td>
<td><a th:href="@{/done/edit/{id}(id=${done.pk})}"><span th:text="${#temporals.format(done.timeUntil, 'HH:mm')}"></span></a></td>
<td><a th:href="@{/done/edit/{id}(id=${done.pk})}"><span th:text="${done.project.name}"></span></a></td>
<td><a th:href="@{/done/edit/{id}(id=${done.pk})}"><span th:text="${done.module.name}"></span></a></td>
<td><a th:href="@{/done/edit/{id}(id=${done.pk})}"><span 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="hoverlink" th:href="@{/done/edit/{id}(id=${done.pk})}"><span th:text="${done.timeNote}"></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><span th:text="${done.timeDiff}"></span></td>
<td><a th:href="@{/done/edit/{id}(id=${done.pk})}" th:title="${done.pk}"><i class="fa fa-edit"></i></a></td>
</tr>
</tbody>
<tfoot>
<tr>
<td>Zusammenfassung</td>
<td>Start: <span class="emphgreen" th:text="${sum.start}"></span></td>
<td>Ende: <span class="emphgreen" th:text="${sum.end}"></span></td>
<td>Arbeitszeit total: <span class="emphblue" th:text="${sum.total}"></span></td>
<td>Pausezeit total: <span class="emphorange" th:text="${sum.pause}"></span></td>
<td>Überstunden: <span class="emphred" th:text="${sum.overdue}"></span></td>
</tr>
</tfoot>
</table>
</div>
<div id="div_summary" class="tab-pane fade">Zusammenfassung</div>

View File

@ -7,7 +7,7 @@
<body>
<font layout:fragment="title">Notizen</font>
<ul layout:fragment="menu">
<li class="nav-item" sec:authorize="hasRole('timetrack_user')"><a class="nav-link" th:href="@{/note/add}">Neue Notiz
<li class="nav-item" sec:authorize="hasRole('timetrack_user')"><a class="nav-link btn btn-success btn-white-text" th:href="@{/note/add}">Neue Notiz
anlegen</a></li>
</ul>
<main layout:fragment="content">