calendar like slot overview
This commit is contained in:
@ -60,7 +60,8 @@ public class DoneController extends CommonController {
|
|||||||
model.addAttribute("sum", sumBean);
|
model.addAttribute("sum", sumBean);
|
||||||
model.addAttribute("daysum", doneService.getDaysum(day, username));
|
model.addAttribute("daysum", doneService.getDaysum(day, username));
|
||||||
model.addAttribute("overtimeBean", doneService.getOvertimeBean(username));
|
model.addAttribute("overtimeBean", doneService.getOvertimeBean(username));
|
||||||
model.addAttribute("slots", doneService.getSlots(username));
|
model.addAttribute("slots", doneService.getSlots(day, username));
|
||||||
|
model.addAttribute("slotOffset", doneService.getSlotOffset(day));
|
||||||
model.addAttribute("schedule", weekBean.toJson());
|
model.addAttribute("schedule", weekBean.toJson());
|
||||||
model.addAttribute("recentList", doneService.getListRecent(username, 10));
|
model.addAttribute("recentList", doneService.getListRecent(username, 10));
|
||||||
model.addAttribute("projectList", doneService.getProjects(false));
|
model.addAttribute("projectList", doneService.getProjects(false));
|
||||||
|
@ -9,9 +9,9 @@ import java.time.Duration;
|
|||||||
import java.time.LocalDate;
|
import java.time.LocalDate;
|
||||||
import java.time.LocalDateTime;
|
import java.time.LocalDateTime;
|
||||||
import java.time.LocalTime;
|
import java.time.LocalTime;
|
||||||
import java.util.ArrayList;
|
import java.util.HashMap;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
import java.util.List;
|
import java.util.Map;
|
||||||
|
|
||||||
import org.apache.logging.log4j.LogManager;
|
import org.apache.logging.log4j.LogManager;
|
||||||
import org.apache.logging.log4j.Logger;
|
import org.apache.logging.log4j.Logger;
|
||||||
@ -156,7 +156,7 @@ public class DoneRepository {
|
|||||||
sql.execute();
|
sql.execute();
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<SlotBean> getSlots(String login) {
|
public Map<LocalDate, SlotBean> getSlots(LocalDate from, LocalDate until, String login) {
|
||||||
SelectSeekStep1<Record3<Integer, LocalDate, Integer>, LocalDate> sql = jooq
|
SelectSeekStep1<Record3<Integer, LocalDate, Integer>, LocalDate> sql = jooq
|
||||||
// @formatter:off
|
// @formatter:off
|
||||||
.select(T_REQUIRED_WORKTIME.PK_REQUIRED_WORKTIME,
|
.select(T_REQUIRED_WORKTIME.PK_REQUIRED_WORKTIME,
|
||||||
@ -165,17 +165,21 @@ public class DoneRepository {
|
|||||||
.from(T_REQUIRED_WORKTIME)
|
.from(T_REQUIRED_WORKTIME)
|
||||||
.innerJoin(T_LOGIN).on(T_LOGIN.PK.eq(T_REQUIRED_WORKTIME.FK_LOGIN))
|
.innerJoin(T_LOGIN).on(T_LOGIN.PK.eq(T_REQUIRED_WORKTIME.FK_LOGIN))
|
||||||
.where(T_LOGIN.LOGIN.eq(login))
|
.where(T_LOGIN.LOGIN.eq(login))
|
||||||
|
.and(T_REQUIRED_WORKTIME.DAY.ge(from))
|
||||||
|
.and(T_REQUIRED_WORKTIME.DAY.le(until))
|
||||||
.orderBy(T_REQUIRED_WORKTIME.DAY);
|
.orderBy(T_REQUIRED_WORKTIME.DAY);
|
||||||
// @formatter:on
|
// @formatter:on
|
||||||
LOGGER.trace(sql);
|
LOGGER.trace(sql);
|
||||||
Iterator<Record3<Integer, LocalDate, Integer>> i = sql.fetch().iterator();
|
Iterator<Record3<Integer, LocalDate, Integer>> i = sql.fetch().iterator();
|
||||||
List<SlotBean> list = new ArrayList<>();
|
Map<LocalDate, SlotBean> map = new HashMap<>();
|
||||||
while (i.hasNext()) {
|
while (i.hasNext()) {
|
||||||
Record3<Integer, LocalDate, Integer> n = i.next();
|
Record3<Integer, LocalDate, Integer> n = i.next();
|
||||||
list.add(SlotBean.of(n.get(T_REQUIRED_WORKTIME.PK_REQUIRED_WORKTIME), n.get(T_REQUIRED_WORKTIME.DAY),
|
LocalDate day = n.get(T_REQUIRED_WORKTIME.DAY);
|
||||||
n.get(T_REQUIRED_WORKTIME.REQUIRED_MINUTES)));
|
Integer pk = n.get(T_REQUIRED_WORKTIME.PK_REQUIRED_WORKTIME);
|
||||||
|
Integer minutes = n.get(T_REQUIRED_WORKTIME.REQUIRED_MINUTES);
|
||||||
|
map.put(day, SlotBean.of(pk, day, minutes));
|
||||||
}
|
}
|
||||||
return list;
|
return map;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -2,8 +2,11 @@ package de.jottyfan.timetrack.modules.done;
|
|||||||
|
|
||||||
import java.time.LocalDate;
|
import java.time.LocalDate;
|
||||||
import java.time.LocalDateTime;
|
import java.time.LocalDateTime;
|
||||||
|
import java.time.YearMonth;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
import org.apache.logging.log4j.LogManager;
|
import org.apache.logging.log4j.LogManager;
|
||||||
import org.apache.logging.log4j.Logger;
|
import org.apache.logging.log4j.Logger;
|
||||||
@ -39,7 +42,7 @@ public class DoneService {
|
|||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private TimeService timeService;
|
private TimeService timeService;
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private DoneRepository repository;
|
private DoneRepository repository;
|
||||||
|
|
||||||
@ -246,11 +249,42 @@ public class DoneService {
|
|||||||
repository.upsertOvertime(bean.getId(), username, bean.getImpact(), bean.getOvertimeMinutes());
|
repository.upsertOvertime(bean.getId(), username, bean.getImpact(), bean.getOvertimeMinutes());
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<SlotBean> getSlots(String username) {
|
public List<SlotBean> getSlots(LocalDate day, String username) {
|
||||||
return repository.getSlots(username);
|
YearMonth ym = YearMonth.from(day);
|
||||||
|
LocalDate from = ym.atDay(1);
|
||||||
|
LocalDate until = ym.atEndOfMonth();
|
||||||
|
Map<LocalDate, SlotBean> map = new HashMap<>();
|
||||||
|
LocalDate i = from;
|
||||||
|
while (i.isBefore(until.plusDays(1))) {
|
||||||
|
map.put(i, SlotBean.of(i));
|
||||||
|
i = i.plusDays(1);
|
||||||
|
}
|
||||||
|
map.putAll(repository.getSlots(from, until, username));
|
||||||
|
List<SlotBean> list = new ArrayList<>(map.values());
|
||||||
|
list.sort((o1, o2) -> {
|
||||||
|
return o1 == null || o2 == null || o1.getDay() == null ? 0 : o1.getDay().compareTo(o2.getDay());
|
||||||
|
});
|
||||||
|
return list;
|
||||||
}
|
}
|
||||||
|
|
||||||
public SlotBean getSlot(Integer id, String username) {
|
public SlotBean getSlot(Integer id, String username) {
|
||||||
return repository.getSlot(id, username);
|
return repository.getSlot(id, username);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* get a list of days until the 1st of the month starts in the calendar - start
|
||||||
|
* with sunday for the matrix
|
||||||
|
*
|
||||||
|
* @param day the day; only the month will be used
|
||||||
|
* @return a list of numbers
|
||||||
|
*/
|
||||||
|
public List<Integer> getSlotOffset(LocalDate day) {
|
||||||
|
List<Integer> list = new ArrayList<Integer>();
|
||||||
|
YearMonth ym = YearMonth.from(day);
|
||||||
|
LocalDate first = ym.atDay(1);
|
||||||
|
for (int i = 0; i < first.getDayOfWeek().getValue(); i++) {
|
||||||
|
list.add(i);
|
||||||
|
}
|
||||||
|
return list;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -22,6 +22,12 @@ public class SlotBean implements Serializable {
|
|||||||
bean.setMinutes(minutes);
|
bean.setMinutes(minutes);
|
||||||
return bean;
|
return bean;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static final SlotBean of(LocalDate day) {
|
||||||
|
SlotBean bean = new SlotBean();
|
||||||
|
bean.setDay(day);
|
||||||
|
return bean;
|
||||||
|
}
|
||||||
|
|
||||||
public String printTime() {
|
public String printTime() {
|
||||||
Integer hours = 0;
|
Integer hours = 0;
|
||||||
@ -74,6 +80,4 @@ public class SlotBean implements Serializable {
|
|||||||
public void setId(Integer id) {
|
public void setId(Integer id) {
|
||||||
this.id = id;
|
this.id = id;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -406,7 +406,7 @@ body {
|
|||||||
|
|
||||||
.slot_badge {
|
.slot_badge {
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
margin-bottom: 2px;
|
margin-bottom: 4px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.slot_badge_left {
|
.slot_badge_left {
|
||||||
@ -415,6 +415,8 @@ body {
|
|||||||
background-color: #ccc;
|
background-color: #ccc;
|
||||||
color: black;
|
color: black;
|
||||||
padding-left: 2px;
|
padding-left: 2px;
|
||||||
|
padding-top: 2px;
|
||||||
|
padding-bottom: 2px;
|
||||||
}
|
}
|
||||||
|
|
||||||
[data-bs-theme=dark] .slot_badge_left {
|
[data-bs-theme=dark] .slot_badge_left {
|
||||||
@ -424,8 +426,8 @@ body {
|
|||||||
.slot_badge_middle {
|
.slot_badge_middle {
|
||||||
border-top: 1px solid silver;
|
border-top: 1px solid silver;
|
||||||
border-bottom: 1px solid silver;
|
border-bottom: 1px solid silver;
|
||||||
padding-left: 2px;
|
padding: 2px;
|
||||||
padding-right: 2px;
|
text-decoration: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
.slot_badge_middle:hover {
|
.slot_badge_middle:hover {
|
||||||
@ -439,8 +441,24 @@ body {
|
|||||||
background-color: transparent;
|
background-color: transparent;
|
||||||
color: black;
|
color: black;
|
||||||
padding-right: 2px;
|
padding-right: 2px;
|
||||||
|
padding-top: 2px;
|
||||||
|
padding-bottom: 2px;
|
||||||
}
|
}
|
||||||
|
|
||||||
[data-bs-theme=dark] .slot_badge_right {
|
[data-bs-theme=dark] .slot_badge_right {
|
||||||
color: white;
|
color: white;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.flex-row-weekday {
|
||||||
|
display: flex;
|
||||||
|
flex-flow: row wrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
.row-weekday > .col {
|
||||||
|
flex: 0 1 calc(100%/7);
|
||||||
|
max-width: calc(100%/7);
|
||||||
|
}
|
||||||
|
|
||||||
|
.boldy {
|
||||||
|
font-weight: bolder;
|
||||||
|
}
|
||||||
|
@ -243,17 +243,33 @@
|
|||||||
<div id="div_slot" class="tab-pane fade tab-pane-table">
|
<div id="div_slot" class="tab-pane fade tab-pane-table">
|
||||||
<div class="alert alert-info">
|
<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.
|
Zur Berechnung der täglichen Überstunden müssen Slots angelegt werden, die definieren, an welchen Tagen wieviele Stunden zu arbeiten ist.
|
||||||
Urlaub und Arbeitsbefreiung können durch das Entfernen des jeweiligen Slots ermöglicht werden.
|
Die Überstundenberechnung hängt von der Vollständigkeit der vorhandenen Slots ab; fehlen Slots, wird die Arbeitszeit jener Tage nicht eingerechnet.<br />
|
||||||
Die Überstundenberechnung hängt von der Vollständigkeit der vorhandenen Slots ab; fehlen Slots, wird die Arbeitszeit jener Tage nicht eingerechnet.
|
Hier werden nur die Slots für diesen Monat angezeigt.
|
||||||
</div>
|
</div>
|
||||||
<div class="container">
|
<div class="container">
|
||||||
<div class="row">
|
<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}">
|
<div class="col slot_badge" th:each="s : ${slots}">
|
||||||
<span class="slot_badge_left" th:text="${#temporals.format(s.day, 'EEE, dd.MM.yyyy')}"></span><a th:href="@{/done/slot/{id}(id=${s.id})}" class="slot_badge_middle"><i class="fas fa-pencil"></i></a><span class="slot_badge_right" th:text="${s.printTime()}"></span>
|
<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>
|
</div>
|
||||||
TODO: nur die Slots dieses Monats anzeigen, damit die Ladezeit nicht unnötig belastet wird
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<script type="text/javascript">
|
<script type="text/javascript">
|
||||||
|
Reference in New Issue
Block a user