schedule for weeks

This commit is contained in:
Jörg Henke
2022-07-27 14:46:25 +02:00
parent 676fa63471
commit af956f4650
13 changed files with 178 additions and 38 deletions

View File

@ -6,6 +6,13 @@
<attribute name="gradle_used_by_scope" value="main,test"/>
</attributes>
</classpathentry>
<classpathentry kind="src" output="bin/test" path="src/test/java">
<attributes>
<attribute name="gradle_scope" value="test"/>
<attribute name="gradle_used_by_scope" value="test"/>
<attribute name="test" value="true"/>
</attributes>
</classpathentry>
<classpathentry kind="src" output="bin/main" path="src/main/resources">
<attributes>
<attribute name="gradle_scope" value="main"/>

View File

@ -2,31 +2,41 @@
<wb-module deploy-name="timetrack">
<property name="context-root" value="timetrack"/>
<wb-resource deploy-path="/WEB-INF/classes" source-path="src/main/resources"/>
<wb-resource deploy-path="/WEB-INF/classes" source-path="src/main/webapp"/>
<wb-resource deploy-path="/WEB-INF/classes" source-path="src/main/java"/>
<wb-resource deploy-path="/" source-path="src/main/webapp"/>
<wb-resource deploy-path="/WEB-INF/classes" source-path="/src/main/java"/>
<wb-resource deploy-path="/WEB-INF/classes" source-path="/src/main/resources"/>
<wb-resource deploy-path="/WEB-INF/classes" source-path="/src/test/java"/>
@ -34,4 +44,5 @@
</project-modules>

View File

@ -5,7 +5,7 @@ plugins {
}
group = 'de.jottyfan'
version = '1.2.3'
version = '1.2.4'
sourceCompatibility = '11'
ext['spring-framework.version'] = '5.3.18'
@ -51,6 +51,7 @@ dependencies {
implementation 'org.springframework.boot:spring-boot-starter-security'
implementation 'org.springframework.boot:spring-boot-starter-thymeleaf'
implementation 'org.springframework.boot:spring-boot-starter-web'
implementation 'org.springframework.boot:spring-boot-starter-test'
implementation 'org.thymeleaf.extras:thymeleaf-extras-springsecurity5'
implementation 'de.jottyfan:timetrackjooq:0.1.1'

View File

@ -0,0 +1,28 @@
package de.jottyfan.timetrack.help;
import java.time.DayOfWeek;
import java.time.LocalDate;
/**
*
* @author henkej
*
*/
public class LocalDateHelper {
/**
* find the day of the week in relation to day
*
* @param day the day to start the search from
* @param dayOfWeek the day of the week that is wanted
* @param backwards if true, search before day, if false, search after day
* @return the found date
*/
public static final LocalDate seekDay(LocalDate day, DayOfWeek dayOfWeek, boolean backwards) {
LocalDate found = day;
while (!found.getDayOfWeek().equals(dayOfWeek)) {
found = backwards ? found.minusDays(1) : found.plusDays(1);
}
return found;
}
}

View File

@ -76,7 +76,8 @@ public class DoneBean implements Serializable, Comparable<DoneBean> {
public final String toJson() {
StringBuilder buf = new StringBuilder("{");
buf.append("\"from\": ").append(nullable(timeFrom, "HH:mm"));
buf.append("\"daySlot\": ").append(day == null ? "null" : day.getDayOfWeek().getValue());
buf.append(", \"from\": ").append(nullable(timeFrom, "HH:mm"));
buf.append(", \"until\": ").append(nullable(timeUntil, "HH:mm"));
buf.append(", \"billing\": ").append(nullable(billing, null));
buf.append("}");

View File

@ -45,11 +45,13 @@ public class DoneController {
Duration maxWorkTime = Duration.ofHours(8); // TODO: to the configuration file
LocalDate day = doneModel.getDay();
List<DoneBean> list = doneService.getList(day, username);
List<DoneBean> week = doneService.getWeek(day, username);
SummaryBean bean = new SummaryBean(list, day, maxWorkTime);
SummaryBean weekBean = new SummaryBean(week, day, maxWorkTime);
model.addAttribute("doneList", list);
model.addAttribute("doneModel", doneModel);
model.addAttribute("sum", bean);
model.addAttribute("schedule", bean.toJson()); // TODO: add the other days of that week
model.addAttribute("schedule", weekBean.toJson());
model.addAttribute("projectList", doneService.getProjects(false));
model.addAttribute("moduleList", doneService.getModules(false));
model.addAttribute("jobList", doneService.getJobs(false));

View File

@ -5,7 +5,6 @@ import java.util.List;
import javax.servlet.http.HttpServletRequest;
import de.jottyfan.timetrack.db.done.tables.records.TProjectRecord;
import de.jottyfan.timetrack.db.done.tables.records.VBillingRecord;
import de.jottyfan.timetrack.db.done.tables.records.VJobRecord;
import de.jottyfan.timetrack.db.done.tables.records.VModuleRecord;
@ -18,20 +17,13 @@ import de.jottyfan.timetrack.db.done.tables.records.VProjectRecord;
*/
public interface IDoneService {
public List<DoneBean> getList(LocalDate day, String username);
public List<DoneBean> getWeek(LocalDate day, String username);
public DoneBean getBean(Integer id);
public String getCurrentUser(HttpServletRequest request);
public List<VProjectRecord> getProjects(boolean includeNull);
public List<VModuleRecord> getModules(boolean includeNull);
public List<VJobRecord> getJobs(boolean includeNull);
public List<VBillingRecord> getBillings(boolean includeNull);
public Integer doUpsert(DoneBean bean, String username);
public Integer doDelete(Integer id);
}

View File

@ -4,7 +4,6 @@ import java.io.Serializable;
import java.time.Duration;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.List;
/**
@ -19,6 +18,12 @@ public class SummaryBean implements Serializable {
private final LocalDate day;
private final List<DoneBean> list;
/**
* @param list the list of beans
* @param day the day that this selection refers to; might be the day
* of the week for weekly sets
* @param maxDayWorktime the maximum work time of a day
*/
public SummaryBean(List<DoneBean> list, LocalDate day, Duration maxDayWorktime) {
this.list = list;
this.day = day;
@ -27,9 +32,9 @@ public class SummaryBean implements Serializable {
public String toJson() {
StringBuilder buf = new StringBuilder("{");
buf.append("\"maxDayWorktime\": \"").append(String.format("%02d:%02d", maxDayWorktime.toHoursPart(), maxDayWorktime.toMinutesPart()));
buf.append("\", \"daySlot\": ").append(day == null ? "null" : day.getDayOfWeek().getValue());
buf.append(", \"schedule\": [");
buf.append("\"maxDayWorktime\": \"")
.append(String.format("%02d:%02d", maxDayWorktime.toHoursPart(), maxDayWorktime.toMinutesPart()));
buf.append("\", \"schedule\": [");
boolean first = true;
for (DoneBean bean : list) {
if (!first) {

View File

@ -8,6 +8,7 @@ import static de.jottyfan.timetrack.db.done.Tables.V_PROJECT;
import static de.jottyfan.timetrack.db.profile.Tables.T_LOGIN;
import java.sql.SQLException;
import java.time.DayOfWeek;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.ArrayList;
@ -34,6 +35,7 @@ import de.jottyfan.timetrack.db.done.tables.records.VJobRecord;
import de.jottyfan.timetrack.db.done.tables.records.VModuleRecord;
import de.jottyfan.timetrack.db.done.tables.records.VProjectRecord;
import de.jottyfan.timetrack.db.profile.tables.records.TLoginRecord;
import de.jottyfan.timetrack.help.LocalDateHelper;
import de.jottyfan.timetrack.spring.done.DoneBean;
/**
@ -216,19 +218,19 @@ public class DoneGateway {
}
/**
* get list of entries of day
* get list of entries of interval
*
* @param day the day
* @param start the lower limit
* @param end the upper limit
* @param userId the id of the user
*
* @return a list (an empty one at least)
* @throws SQLException
* @throws ClassNotFoundException
* @throws DataAccessException
*/
public List<DoneBean> getAllOfDay(LocalDate day, Integer userId)
private List<DoneBean> getAllOfInterval(LocalDateTime start, LocalDateTime end, Integer userId)
throws DataAccessException, ClassNotFoundException, SQLException {
LocalDateTime dayStart = day.atStartOfDay();
LocalDateTime dayEnd = day.atTime(23, 59, 59);
SelectConditionStep<Record7<Integer, LocalDateTime, LocalDateTime, Integer, Integer, Integer, Integer>> sql = getJooq()
// @formatter:off
.select(T_DONE.PK,
@ -239,8 +241,8 @@ public class DoneGateway {
T_DONE.FK_JOB,
T_DONE.FK_BILLING)
.from(T_DONE)
.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()))
.where(T_DONE.TIME_FROM.between(start, end).or(T_DONE.TIME_FROM.isNull()))
.and(T_DONE.TIME_UNTIL.between(start, end).or(T_DONE.TIME_UNTIL.isNull()))
.and(T_DONE.FK_LOGIN.eq(userId == null ? -999999 : userId));
// @formatter:on
LOGGER.debug("{}", sql.toString());
@ -265,6 +267,40 @@ public class DoneGateway {
return list;
}
/**
* get list of entries of day
*
* @param day the day
*
* @return a list (an empty one at least)
* @throws SQLException
* @throws ClassNotFoundException
* @throws DataAccessException
*/
public List<DoneBean> getAllOfDay(LocalDate day, Integer userId)
throws DataAccessException, ClassNotFoundException, SQLException {
LocalDateTime dayStart = day.atStartOfDay();
LocalDateTime dayEnd = day.atTime(23, 59, 59);
return getAllOfInterval(dayStart, dayEnd, userId);
}
/**
* get all entries of the week where day belongs to
*
* @param day the day that the week refers to
* @param userId the id of the user
* @return a list of done beans; an empty one at least
* @throws SQLException
* @throws ClassNotFoundException
* @throws DataAccessException
*/
public List<DoneBean> getAllOfWeek(LocalDate day, Integer userId)
throws DataAccessException, ClassNotFoundException, SQLException {
LocalDate sunday = LocalDateHelper.seekDay(day, DayOfWeek.SUNDAY, true);
LocalDate saturday = LocalDateHelper.seekDay(day, DayOfWeek.SATURDAY, false);
return getAllOfInterval(sunday.atStartOfDay(), saturday.atTime(23, 59, 59), userId);
}
/**
* delete an entry from the database
*

View File

@ -57,6 +57,22 @@ public class DoneService implements IDoneService {
}
}
@Override
public List<DoneBean> getWeek(LocalDate day, String username) {
try {
DoneGateway gw = new DoneGateway(dsl);
Integer userId = gw.getUserId(username);
if (userId == null) {
LOGGER.warn("userId of user {} is null", username);
}
return gw.getAllOfWeek(day, userId);
} catch (Exception e) {
LOGGER.error(e);
return new ArrayList<>();
}
}
@Override
public DoneBean getBean(Integer id) {
try {

View File

@ -17,16 +17,32 @@ class Schedule {
drawBackgroundDay = function(ctx, width, height, offsetx) {
var hourHeight = parseInt(height / 24);
var fs = ["#eeeeee", "#bbbbbb", "#eeeeee", "#bbbbbb", "#eeeeee", "#bbbbbb",
"#faf0fa", "#d9cbd9", "#faf0fa", "#9acbd9", "#cdf0fa", "#9acbd9",
"#cdf0fa", "#9acbd9", "#cdf0fa", "#d9cbd9", "#faf0fa", "#d9cbd9",
"#faf0fa", "#d9cbd9", "#eeeeee", "#bbbbbb", "#eeeeee", "#bbbbbb"];
for (var i = 0; i < 24; i++) {
var x = parseInt(offsetx);
var y = parseInt(i * hourHeight);
var w = parseInt(width);
var h = parseInt(hourHeight);
ctx.fillStyle = (i > 8 & i <= 17) ? (i % 2 ? "#cdf0fa" : "#9acbd9") : (i % 2 ? "#faf0fa" : "#d9cbd9");
ctx.fillStyle = fs[i];
ctx.fillRect(x, y, w, h);
}
ctx.lineWidth = 1;
ctx.strokeStyle = "white";
ctx.strokeRect(offsetx, 0, width, height);
ctx.strokeStyle = "black";
ctx.lineWidth = 2;
ctx.moveTo(parseInt(offsetx), parseInt(hourHeight * 6));
ctx.lineTo(parseInt(offsetx + width), parseInt(hourHeight * 6));
ctx.stroke();
ctx.moveTo(parseInt(offsetx), parseInt(hourHeight * 12));
ctx.lineTo(parseInt(offsetx + width), parseInt(hourHeight * 12));
ctx.stroke();
ctx.moveTo(parseInt(offsetx), parseInt(hourHeight * 18));
ctx.lineTo(parseInt(offsetx + width), parseInt(hourHeight * 18));
ctx.stroke();
}
drawBackgroundWeek = function(ctx, width, height) {

View File

@ -191,7 +191,6 @@
var ctx = $("#scheduleCanvas")[0].getContext("2d");
var currentDayRecords = JSON.parse('[(${schedule})]');
var scheduleRecords = currentDayRecords.schedule;
var daySlot = currentDayRecords.daySlot;
for (var i = 0; i < scheduleRecords.length; i++) {
var r = scheduleRecords[i];
var cssClass = r.billing;
@ -206,7 +205,7 @@
color = "#00aa00";
}
/* daySlot 7 = sunday, but this should be slot 0 */
schedule.drawSlot(ctx, daySlot > 6 ? 0 : daySlot, r.from, r.until, "black", color);
schedule.drawSlot(ctx, r.daySlot > 6 ? 0 : r.daySlot, r.from, r.until, "black", color);
}
var localeUrl = '[[@{/js/dataTables/de.json}]]';
$("#project_table").DataTable({

View File

@ -0,0 +1,26 @@
package de.jottyfan.timetrack.help;
import static org.junit.jupiter.api.Assertions.assertEquals;
import java.time.DayOfWeek;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import org.junit.jupiter.api.Test;
/**
*
* @author henkej
*
*/
public class TestLocalDateHelper {
@Test
public void testFindWeekDays() {
assertEquals(20, LocalDateHelper.seekDay(LocalDate.of(2022, 2, 23), DayOfWeek.SUNDAY, true).getDayOfMonth());
assertEquals(26, LocalDateHelper.seekDay(LocalDate.of(2022, 2, 23), DayOfWeek.SATURDAY, false).getDayOfMonth());
assertEquals(13, LocalDateHelper.seekDay(LocalDate.of(2022, 2, 19), DayOfWeek.SUNDAY, true).getDayOfMonth());
assertEquals(19, LocalDateHelper.seekDay(LocalDate.of(2022, 2, 19), DayOfWeek.SATURDAY, false).getDayOfMonth());
assertEquals("26.12.2021", LocalDateHelper.seekDay(LocalDate.of(2022, 1, 1), DayOfWeek.SUNDAY, true).format(DateTimeFormatter.ofPattern("dd.MM.yyyy")));
assertEquals("02.01.2022", LocalDateHelper.seekDay(LocalDate.of(2021, 12, 31), DayOfWeek.SUNDAY, false).format(DateTimeFormatter.ofPattern("dd.MM.yyyy")));
}
}