From 25b0288f3eecc85559f81adbd5eedb73b7f35259 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rg=20Henke?= Date: Thu, 5 May 2022 14:52:21 +0200 Subject: [PATCH] show work times --- .../timetrack/spring/done/DoneBean.java | 231 +++++++++++++++- .../timetrack/spring/done/DoneController.java | 11 +- .../timetrack/spring/done/DoneModel.java | 37 +++ .../timetrack/spring/done/IDoneService.java | 16 +- .../spring/done/impl/DoneGateway.java | 251 ++++++++++++++++++ .../spring/done/impl/DoneService.java | 71 ++++- .../timetrack/modules/done/DoneBean.java | 226 ---------------- src/main/resources/static/css/style.css | 24 +- src/main/resources/templates/done/list.html | 112 +++++++- src/main/resources/templates/layout/main.html | 1 + 10 files changed, 714 insertions(+), 266 deletions(-) create mode 100644 src/main/java/de/jottyfan/timetrack/spring/done/DoneModel.java create mode 100644 src/main/java/de/jottyfan/timetrack/spring/done/impl/DoneGateway.java delete mode 100644 src/main/old/de/jottyfan/timetrack/modules/done/DoneBean.java diff --git a/src/main/java/de/jottyfan/timetrack/spring/done/DoneBean.java b/src/main/java/de/jottyfan/timetrack/spring/done/DoneBean.java index d1b7785..1eb9509 100644 --- a/src/main/java/de/jottyfan/timetrack/spring/done/DoneBean.java +++ b/src/main/java/de/jottyfan/timetrack/spring/done/DoneBean.java @@ -1,20 +1,239 @@ package de.jottyfan.timetrack.spring.done; import java.io.Serializable; +import java.time.Duration; +import java.time.LocalDate; +import java.time.LocalDateTime; +import java.time.ZoneId; +import java.time.format.DateTimeFormatter; +import java.util.Date; +import java.util.Map; + +import de.jottyfan.timetrack.db.done.tables.records.TBillingRecord; +import de.jottyfan.timetrack.db.done.tables.records.TDoneRecord; +import de.jottyfan.timetrack.db.done.tables.records.TJobRecord; +import de.jottyfan.timetrack.db.done.tables.records.TModuleRecord; +import de.jottyfan.timetrack.db.done.tables.records.TProjectRecord; /** * * @author henkej * */ -public class DoneBean implements Serializable, Comparable{ - +public class DoneBean implements Serializable, Comparable { private static final long serialVersionUID = 1L; - @Override - public int compareTo(DoneBean bean) { - // TODO: implement - return 0; + private static final DateTimeFormatter hhmm = DateTimeFormatter.ofPattern("HH:mm"); + + private Integer pk; + private LocalDateTime timeFrom; + private LocalDateTime timeUntil; + private TProjectRecord project; + private TModuleRecord module; + private TJobRecord activity; + private TBillingRecord billing; + + public DoneBean() { } + public DoneBean(TDoneRecord r, Map projectMap, Map moduleMap, + Map jobMap, Map billingMap) { + this.pk = r.getPk(); + this.timeFrom = r.getTimeFrom(); + this.timeUntil = r.getTimeUntil(); + this.project = projectMap.get(r.getFkProject()); + this.module = moduleMap.get(r.getFkModule()); + this.activity = jobMap.get(r.getFkJob()); + this.billing = billingMap.get(r.getFkBilling()); + } + + @Override + public final String toString() { + StringBuilder buf = new StringBuilder("DoneBean{"); + buf.append("pk=").append(pk); + buf.append(",timeFrom=").append(timeFrom == null ? "" : timeFrom.format(DateTimeFormatter.ISO_DATE_TIME)); + buf.append(",timeUntil=").append(timeUntil == null ? "" : timeUntil.format(DateTimeFormatter.ISO_DATE_TIME)); + buf.append(",project=").append(project == null ? "" : project.getName()); + buf.append(",module=").append(module == null ? "" : module.getName()); + buf.append(",activity=").append(activity == null ? "" : activity.getName()); + buf.append(",billing=").append(billing == null ? "" : billing.getName()); + buf.append("}"); + return buf.toString(); + } + + /** + * set the day of timeFrom and timeUntil, keeping the times + * + * @param day the day + */ + public void setDay(Date day) { + if (timeFrom != null) { + LocalDateTime ldt = timeFrom; + LocalDate date = day.toInstant().atZone(ZoneId.systemDefault()).toLocalDate(); + ldt = ldt.withYear(date.getYear()).withMonth(date.getMonthValue()).withDayOfMonth(date.getDayOfMonth()); + timeFrom = ldt; + } + if (timeUntil != null) { + LocalDateTime ldt = timeUntil; + LocalDate date = day.toInstant().atZone(ZoneId.systemDefault()).toLocalDate(); + ldt = ldt.withYear(date.getYear()).withMonth(date.getMonthValue()).withDayOfMonth(date.getDayOfMonth()); + timeUntil = ldt; + } + } + + public String getTimeSummary() { + StringBuilder buf = new StringBuilder(); + if (timeFrom != null) { + buf.append(timeFrom.format(hhmm)); + } + if (timeUntil != null) { + buf.append(" - "); + buf.append(timeUntil.format(hhmm)); + } + return buf.toString(); + } + + @Override + public int compareTo(DoneBean o) { + return o == null || timeFrom == null || o.getTimeFrom() == null ? 0 : timeFrom.compareTo(o.getTimeFrom()); + } + + public String getTimeDiff() { + LocalDateTime earlier = timeFrom != null ? timeFrom : LocalDateTime.now(); + LocalDateTime later = timeUntil != null ? timeUntil : LocalDateTime.now(); + Duration diff = Duration.between(earlier, later); + return String.format("%02d:%02d", diff.toHours(), diff.toMinutes() % 60); + } + + /** + * get local date time from s + * + * @param s the HH:mm formatted values + * @param ldt the date as basic for that datetime, for today one can use + * LocalDateTime.now(); in fact this is set if ldt is null internally + * @return the generated datetime + */ + public LocalDateTime getLocalDateTimeFromHHmm(String s, LocalDateTime ldt) { + if (s == null || s.trim().isEmpty()) { + return null; + } else if (ldt == null) { + ldt = LocalDateTime.now(); + } + String[] hm = s.split(":"); + Integer hours = 0; + Integer minutes = 0; + if (hm.length > 0) { + hours = Integer.valueOf(hm[0]); + } + if (hm.length > 1) { + minutes = Integer.valueOf(hm[1]); + } + ldt = ldt.withHour(hours); + ldt = ldt.withMinute(minutes); + ldt = ldt.withSecond(0); + ldt = ldt.withNano(0); + return ldt; + } + + public String getProjectName() { + return project == null ? "" : project.getName(); + } + + public String getModuleName() { + return module == null ? "" : module.getName(); + } + + public String getJobName() { + return activity == null ? "" : activity.getName(); + } + + public String getBillingName() { + return billing == null ? "" : billing.getName(); + } + + public String getBillingShortcut() { + return billing == null ? "" : billing.getShortcut(); + } + + public String getBillingCsskey() { + return billing == null ? "" : billing.getCsskey(); + } + + public String getTimeFromString() { + return timeFrom == null ? "" : timeFrom.format(hhmm); + } + + public void setTimeFromString(String s) { + this.timeFrom = getLocalDateTimeFromHHmm(s, null); // use setDay instead + } + + public String getTimeUntilString() { + return timeUntil == null ? "" : timeUntil.format(hhmm); + } + + public void setTimeUntilString(String s) { + this.timeUntil = getLocalDateTimeFromHHmm(s, null); // use setDay instead + } + + public Integer getPk() { + return this.pk; + } + + public void setPk(Integer pk) { + this.pk = pk; + } + + public LocalDateTime getTimeFrom() { + return timeFrom; + } + + public void setTimeFrom(LocalDateTime timeFrom) { + this.timeFrom = timeFrom; + } + + public LocalDateTime getTimeUntil() { + return timeUntil; + } + + public void setTimeUntil(LocalDateTime timeUntil) { + this.timeUntil = timeUntil; + } + + public TProjectRecord getProject() { + return project; + } + + public void setProject(TProjectRecord project) { + this.project = project; + } + + public TModuleRecord getModule() { + return module; + } + + public void setModule(TModuleRecord module) { + this.module = module; + } + + public TJobRecord getActivity() { + return activity; + } + + public void setActivity(TJobRecord activity) { + this.activity = activity; + } + + /** + * @return the billing + */ + public TBillingRecord getBilling() { + return billing; + } + + /** + * @param billing the billing to set + */ + public void setBilling(TBillingRecord billing) { + this.billing = billing; + } } diff --git a/src/main/java/de/jottyfan/timetrack/spring/done/DoneController.java b/src/main/java/de/jottyfan/timetrack/spring/done/DoneController.java index 51d6c62..908dcd5 100644 --- a/src/main/java/de/jottyfan/timetrack/spring/done/DoneController.java +++ b/src/main/java/de/jottyfan/timetrack/spring/done/DoneController.java @@ -11,6 +11,7 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.ModelAttribute; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; @@ -36,9 +37,15 @@ public class DoneController { @RolesAllowed("timetrack_user") @RequestMapping(value = "/done/list") - public String getList(Model model) { - List list = doneService.getList(); + public String getList(@ModelAttribute DoneModel doneModel, Model model) { + String username = doneService.getCurrentUser(request); + List list = doneService.getList(doneModel.getDay(), username); model.addAttribute("doneList", list); + model.addAttribute("doneModel", doneModel); + model.addAttribute("projectList", doneService.getProjects()); + model.addAttribute("moduleList", doneService.getModules()); + model.addAttribute("jobList", doneService.getJobs()); + model.addAttribute("billingList", doneService.getBillings()); return "done/list"; } diff --git a/src/main/java/de/jottyfan/timetrack/spring/done/DoneModel.java b/src/main/java/de/jottyfan/timetrack/spring/done/DoneModel.java new file mode 100644 index 0000000..aeefc96 --- /dev/null +++ b/src/main/java/de/jottyfan/timetrack/spring/done/DoneModel.java @@ -0,0 +1,37 @@ +package de.jottyfan.timetrack.spring.done; + +import java.io.Serializable; +import java.time.LocalDate; + +import org.springframework.format.annotation.DateTimeFormat; + +/** + * + * @author henkej + * + */ +public class DoneModel implements Serializable { + private static final long serialVersionUID = 1L; + + @DateTimeFormat(pattern = "yyyy-MM-dd") + private LocalDate day; + + public DoneModel() { + this.day = LocalDate.now(); + } + + /** + * @return the day + */ + + public LocalDate getDay() { + return day; + } + + /** + * @param day the day to set + */ + public void setDay(LocalDate day) { + this.day = day; + } +} diff --git a/src/main/java/de/jottyfan/timetrack/spring/done/IDoneService.java b/src/main/java/de/jottyfan/timetrack/spring/done/IDoneService.java index e7f9a2f..336bb69 100644 --- a/src/main/java/de/jottyfan/timetrack/spring/done/IDoneService.java +++ b/src/main/java/de/jottyfan/timetrack/spring/done/IDoneService.java @@ -1,18 +1,32 @@ package de.jottyfan.timetrack.spring.done; +import java.time.LocalDate; import java.util.List; import javax.servlet.http.HttpServletRequest; +import de.jottyfan.timetrack.db.done.tables.records.TBillingRecord; +import de.jottyfan.timetrack.db.done.tables.records.TJobRecord; +import de.jottyfan.timetrack.db.done.tables.records.TModuleRecord; +import de.jottyfan.timetrack.db.done.tables.records.TProjectRecord; + /** * * @author henkej * */ public interface IDoneService { - public List getList(); + public List getList(LocalDate day, String username); public DoneBean getBean(Integer id); public String getCurrentUser(HttpServletRequest request); + + public List getProjects(); + + public List getModules(); + + public List getJobs(); + + public List getBillings(); } diff --git a/src/main/java/de/jottyfan/timetrack/spring/done/impl/DoneGateway.java b/src/main/java/de/jottyfan/timetrack/spring/done/impl/DoneGateway.java new file mode 100644 index 0000000..9f001d2 --- /dev/null +++ b/src/main/java/de/jottyfan/timetrack/spring/done/impl/DoneGateway.java @@ -0,0 +1,251 @@ +package de.jottyfan.timetrack.spring.done.impl; + +import static de.jottyfan.timetrack.db.done.Tables.T_BILLING; +import static de.jottyfan.timetrack.db.done.Tables.T_DONE; +import static de.jottyfan.timetrack.db.done.Tables.T_JOB; +import static de.jottyfan.timetrack.db.done.Tables.T_MODULE; +import static de.jottyfan.timetrack.db.done.Tables.T_PROJECT; +import static de.jottyfan.timetrack.db.profile.Tables.T_LOGIN; + +import java.sql.SQLException; +import java.time.LocalDate; +import java.time.LocalDateTime; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.jooq.DSLContext; +import org.jooq.DeleteConditionStep; +import org.jooq.Record7; +import org.jooq.Result; +import org.jooq.SelectConditionStep; +import org.jooq.exception.DataAccessException; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Repository; + +import de.jottyfan.timetrack.db.done.tables.records.TBillingRecord; +import de.jottyfan.timetrack.db.done.tables.records.TDoneRecord; +import de.jottyfan.timetrack.db.done.tables.records.TJobRecord; +import de.jottyfan.timetrack.db.done.tables.records.TModuleRecord; +import de.jottyfan.timetrack.db.done.tables.records.TProjectRecord; +import de.jottyfan.timetrack.db.profile.tables.records.TLoginRecord; +import de.jottyfan.timetrack.spring.done.DoneBean; + +/** + * + * @author jotty + * + */ +@Repository +public class DoneGateway { + private static final Logger LOGGER = LogManager.getLogger(DoneGateway.class); + private final DSLContext jooq; + + public DoneGateway(@Autowired DSLContext jooq) throws Exception { + this.jooq = jooq; + } + + public DSLContext getJooq() { + return this.jooq; + } + + /** + * get the user id of the user with username + * + * @param username the name of the user + * @return the ID of the user; if not found, null + */ + public Integer getUserId(String username) { + Result r = getJooq().selectFrom(T_LOGIN).where(T_LOGIN.LOGIN.eq(username)).fetch(); + return r == null || r.size() < 1 ? null : r.get(0).getPk(); + } + + /** + * get all projects from the database + * + * @return a list of found projects + * + * @throws DataAccessException + * @throws ClassNotFoundException + * @throws SQLException + */ + public List getAllProjects() throws DataAccessException, ClassNotFoundException, SQLException { + return getJooq().selectFrom(T_PROJECT).fetchInto(TProjectRecord.class); + } + + /** + * get all modules from the database + * + * @return a list of found modules + * + * @throws DataAccessException + * @throws ClassNotFoundException + * @throws SQLException + */ + public List getAllModules() throws DataAccessException, ClassNotFoundException, SQLException { + return getJooq().selectFrom(T_MODULE).fetchInto(TModuleRecord.class); + } + + /** + * get all jobs from the database + * + * @return a list of found jobs + * + * @throws DataAccessException + * @throws ClassNotFoundException + * @throws SQLException + */ + public List getAllJobs() throws DataAccessException, ClassNotFoundException, SQLException { + return getJooq().selectFrom(T_JOB).fetchInto(TJobRecord.class); + } + + /** + * get all billings from the database + * + * @return a list of found billings + * + * @throws DataAccessException + * @throws ClassNotFoundException + * @throws SQLException + */ + public List getAllBillings() throws DataAccessException, ClassNotFoundException, SQLException { + return getJooq().selectFrom(T_BILLING).fetchInto(TBillingRecord.class); + } + + /** + * generate a project map from the database + * + * @return the project map + * @throws SQLException + * @throws ClassNotFoundException + * @throws DataAccessException + */ + private Map getProjectMap() + throws DataAccessException, ClassNotFoundException, SQLException { + Map map = new HashMap<>(); + for (TProjectRecord r : getAllProjects()) { + map.put(r.getPk(), r); + } + return map; + } + + /** + * generate a module map from the database + * + * @return the module map + * @throws SQLException + * @throws ClassNotFoundException + * @throws DataAccessException + */ + private Map getModuleMap() throws DataAccessException, ClassNotFoundException, SQLException { + Map map = new HashMap<>(); + for (TModuleRecord r : getAllModules()) { + map.put(r.getPk(), r); + } + return map; + } + + /** + * generate a job map from the database + * + * @return the job map + * @throws SQLException + * @throws ClassNotFoundException + * @throws DataAccessException + */ + private Map getJobMap() throws DataAccessException, ClassNotFoundException, SQLException { + Map map = new HashMap<>(); + for (TJobRecord r : getAllJobs()) { + map.put(r.getPk(), r); + } + return map; + } + + /** + * generate a billing map from the database + * + * @return the billing map + * @throws SQLException + * @throws ClassNotFoundException + * @throws DataAccessException + */ + private Map getBillingMap() + throws DataAccessException, ClassNotFoundException, SQLException { + Map map = new HashMap<>(); + for (TBillingRecord r : getAllBillings()) { + map.put(r.getPk(), r); + } + return map; + } + + /** + * 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 getAllOfDay(LocalDate day, Integer userId) + throws DataAccessException, ClassNotFoundException, SQLException { + LocalDateTime dayStart = day.atStartOfDay(); + LocalDateTime dayEnd = day.atTime(23, 59, 59); + SelectConditionStep> sql = getJooq() + // @formatter:off + .select(T_DONE.PK, + T_DONE.TIME_FROM, + T_DONE.TIME_UNTIL, + T_DONE.FK_PROJECT, + T_DONE.FK_MODULE, + 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)) + .and(T_DONE.FK_LOGIN.eq(userId == null ? -999999 : userId)); + // @formatter:on + LOGGER.debug("{}", sql.toString()); + List list = new ArrayList<>(); + Map projectMap = getProjectMap(); + Map moduleMap = getModuleMap(); + Map jobMap = getJobMap(); + Map billingMap = getBillingMap(); + for (Record7 r : sql.fetch()) { + DoneBean bean = new DoneBean(); + bean.setPk(r.get(T_DONE.PK)); + bean.setTimeFrom(r.get(T_DONE.TIME_FROM)); + bean.setTimeUntil(r.get(T_DONE.TIME_UNTIL)); + bean.setProject(projectMap.get(r.get(T_DONE.FK_PROJECT))); + bean.setModule(moduleMap.get(r.get(T_DONE.FK_MODULE))); + bean.setActivity(jobMap.get(r.get(T_DONE.FK_JOB))); + bean.setBilling(billingMap.get(r.get(T_DONE.FK_BILLING))); + list.add(bean); + } + list.sort((o1, o2) -> o1 == null ? 0 : o1.compareTo(o2)); + return list; + } + + /** + * delete an entry from the database + * + * @param pk the id of the entry + * @return the number of affected database rows, should be 1 + * @throws SQLException + * @throws ClassNotFoundException + * @throws DataAccessException + */ + public Integer delete(Integer pk) throws DataAccessException, ClassNotFoundException, SQLException { + DeleteConditionStep sql = getJooq() + // @formatter:off + .deleteFrom(T_DONE) + .where(T_DONE.PK.eq(pk)); + // @formatter:on + LOGGER.debug("{}", sql.toString()); + return sql.execute(); + } +} diff --git a/src/main/java/de/jottyfan/timetrack/spring/done/impl/DoneService.java b/src/main/java/de/jottyfan/timetrack/spring/done/impl/DoneService.java index cd9ad11..94b83ba 100644 --- a/src/main/java/de/jottyfan/timetrack/spring/done/impl/DoneService.java +++ b/src/main/java/de/jottyfan/timetrack/spring/done/impl/DoneService.java @@ -1,5 +1,6 @@ package de.jottyfan.timetrack.spring.done.impl; +import java.time.LocalDate; import java.util.ArrayList; import java.util.List; @@ -13,10 +14,12 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; +import de.jottyfan.timetrack.db.done.tables.records.TBillingRecord; +import de.jottyfan.timetrack.db.done.tables.records.TJobRecord; +import de.jottyfan.timetrack.db.done.tables.records.TModuleRecord; +import de.jottyfan.timetrack.db.done.tables.records.TProjectRecord; import de.jottyfan.timetrack.spring.done.DoneBean; import de.jottyfan.timetrack.spring.done.IDoneService; -import de.jottyfan.timetrack.spring.note.NoteBean; -import de.jottyfan.timetrack.spring.note.impl.NoteGateway; import de.jottyfan.timetrack.spring.note.impl.NoteService; /** @@ -31,21 +34,27 @@ public class DoneService implements IDoneService { @Autowired private DSLContext dsl; - + @Override - public String getCurrentUser(HttpServletRequest request) { - KeycloakSecurityContext ksc = (KeycloakSecurityContext) request.getAttribute(KeycloakSecurityContext.class.getName()); + public String getCurrentUser(HttpServletRequest request) { + KeycloakSecurityContext ksc = (KeycloakSecurityContext) request + .getAttribute(KeycloakSecurityContext.class.getName()); return ksc == null ? "" : ksc.getIdToken().getPreferredUsername(); } @Override - public List getList() { -// try { -// return new DoneGateway(dsl).getAll(); -// } catch (Exception e) { -// LOGGER.error(e); + public List getList(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.getAllOfDay(day, userId); + } catch (Exception e) { + LOGGER.error(e); return new ArrayList<>(); -// } + } } @Override @@ -54,4 +63,44 @@ public class DoneService implements IDoneService { return null; } + @Override + public List getProjects() { + try { + return new DoneGateway(dsl).getAllProjects(); + } catch (Exception e) { + LOGGER.error(e); + return new ArrayList<>(); + } + } + + @Override + public List getModules() { + try { + return new DoneGateway(dsl).getAllModules(); + } catch (Exception e) { + LOGGER.error(e); + return new ArrayList<>(); + } + } + + @Override + public List getJobs() { + try { + return new DoneGateway(dsl).getAllJobs(); + } catch (Exception e) { + LOGGER.error(e); + return new ArrayList<>(); + } + } + + @Override + public List getBillings() { + try { + return new DoneGateway(dsl).getAllBillings(); + } catch (Exception e) { + LOGGER.error(e); + return new ArrayList<>(); + } + } + } diff --git a/src/main/old/de/jottyfan/timetrack/modules/done/DoneBean.java b/src/main/old/de/jottyfan/timetrack/modules/done/DoneBean.java deleted file mode 100644 index 9f2891a..0000000 --- a/src/main/old/de/jottyfan/timetrack/modules/done/DoneBean.java +++ /dev/null @@ -1,226 +0,0 @@ -package de.jottyfan.timetrack.modules.done; - -import java.io.Serializable; -import java.time.Duration; -import java.time.LocalDate; -import java.time.LocalDateTime; -import java.time.ZoneId; -import java.time.format.DateTimeFormatter; -import java.util.Date; -import java.util.Map; - -import de.jottyfan.timetrack.db.done.tables.records.TBillingRecord; -import de.jottyfan.timetrack.db.done.tables.records.TDoneRecord; -import de.jottyfan.timetrack.db.done.tables.records.TJobRecord; -import de.jottyfan.timetrack.db.done.tables.records.TModuleRecord; -import de.jottyfan.timetrack.db.done.tables.records.TProjectRecord; -import de.jottyfan.timetrack.modules.Bean; - -/** - * - * @author henkej - * - */ -public class DoneBean implements Bean, Serializable, Comparable { - private static final long serialVersionUID = 1L; - - private static final DateTimeFormatter hhmm = DateTimeFormatter.ofPattern("HH:mm"); - - private Integer pk; - private LocalDateTime timeFrom; - private LocalDateTime timeUntil; - private TProjectRecord project; - private TModuleRecord module; - private TJobRecord activity; - private TBillingRecord billing; - - public DoneBean() { - } - - public DoneBean(TDoneRecord r, Map projectMap, Map moduleMap, - Map jobMap, Map billingMap) { - this.pk = r.getPk(); - this.timeFrom = r.getTimeFrom(); - this.timeUntil = r.getTimeUntil(); - this.project = projectMap.get(r.getFkProject()); - this.module = moduleMap.get(r.getFkModule()); - this.activity = jobMap.get(r.getFkJob()); - this.billing = billingMap.get(r.getFkBilling()); - } - - /** - * set the day of timeFrom and timeUntil, keeping the times - * - * @param day the day - */ - public void setDay(Date day) { - if (timeFrom != null) { - LocalDateTime ldt = timeFrom; - LocalDate date = day.toInstant().atZone(ZoneId.systemDefault()).toLocalDate(); - ldt = ldt.withYear(date.getYear()).withMonth(date.getMonthValue()).withDayOfMonth(date.getDayOfMonth()); - timeFrom = ldt; - } - if (timeUntil != null) { - LocalDateTime ldt = timeUntil; - LocalDate date = day.toInstant().atZone(ZoneId.systemDefault()).toLocalDate(); - ldt = ldt.withYear(date.getYear()).withMonth(date.getMonthValue()).withDayOfMonth(date.getDayOfMonth()); - timeUntil = ldt; - } - } - - public String getTimeSummary() { - StringBuilder buf = new StringBuilder(); - if (timeFrom != null) { - buf.append(timeFrom.format(hhmm)); - } - if (timeUntil != null) { - buf.append(" - "); - buf.append(timeUntil.format(hhmm)); - } - return buf.toString(); - } - - @Override - public int compareTo(DoneBean o) { - return o == null || timeFrom == null || o.getTimeFrom() == null ? 0 : timeFrom.compareTo(o.getTimeFrom()); - } - - public String getTimeDiff() { - LocalDateTime earlier = timeFrom != null ? timeFrom : LocalDateTime.now(); - LocalDateTime later = timeUntil != null ? timeUntil : LocalDateTime.now(); - Duration diff = Duration.between(earlier, later); - return String.format("%02d:%02d", diff.toHours(), diff.toMinutes() % 60); - } - - /** - * get local date time from s - * - * @param s the HH:mm formatted values - * @param ldt the date as basic for that datetime, for today one can use - * LocalDateTime.now(); in fact this is set if ldt is null internally - * @return the generated datetime - */ - public LocalDateTime getLocalDateTimeFromHHmm(String s, LocalDateTime ldt) { - if (s == null || s.trim().isEmpty()) { - return null; - } else if (ldt == null) { - ldt = LocalDateTime.now(); - } - String[] hm = s.split(":"); - Integer hours = 0; - Integer minutes = 0; - if (hm.length > 0) { - hours = Integer.valueOf(hm[0]); - } - if (hm.length > 1) { - minutes = Integer.valueOf(hm[1]); - } - ldt = ldt.withHour(hours); - ldt = ldt.withMinute(minutes); - ldt = ldt.withSecond(0); - ldt = ldt.withNano(0); - return ldt; - } - - public String getProjectName() { - return project == null ? "" : project.getName(); - } - - public String getModuleName() { - return module == null ? "" : module.getName(); - } - - public String getJobName() { - return activity == null ? "" : activity.getName(); - } - - public String getBillingName() { - return billing == null ? "" : billing.getName(); - } - - public String getBillingShortcut() { - return billing == null ? "" : billing.getShortcut(); - } - - public String getBillingCsskey() { - return billing == null ? "" : billing.getCsskey(); - } - - public String getTimeFromString() { - return timeFrom == null ? "" : timeFrom.format(hhmm); - } - - public void setTimeFromString(String s) { - this.timeFrom = getLocalDateTimeFromHHmm(s, null); // use setDay instead - } - - public String getTimeUntilString() { - return timeUntil == null ? "" : timeUntil.format(hhmm); - } - - public void setTimeUntilString(String s) { - this.timeUntil = getLocalDateTimeFromHHmm(s, null); // use setDay instead - } - - public Integer getPk() { - return this.pk; - } - - public void setPk(Integer pk) { - this.pk = pk; - } - - public LocalDateTime getTimeFrom() { - return timeFrom; - } - - public void setTimeFrom(LocalDateTime timeFrom) { - this.timeFrom = timeFrom; - } - - public LocalDateTime getTimeUntil() { - return timeUntil; - } - - public void setTimeUntil(LocalDateTime timeUntil) { - this.timeUntil = timeUntil; - } - - public TProjectRecord getProject() { - return project; - } - - public void setProject(TProjectRecord project) { - this.project = project; - } - - public TModuleRecord getModule() { - return module; - } - - public void setModule(TModuleRecord module) { - this.module = module; - } - - public TJobRecord getActivity() { - return activity; - } - - public void setActivity(TJobRecord activity) { - this.activity = activity; - } - - /** - * @return the billing - */ - public TBillingRecord getBilling() { - return billing; - } - - /** - * @param billing the billing to set - */ - public void setBilling(TBillingRecord billing) { - this.billing = billing; - } -} diff --git a/src/main/resources/static/css/style.css b/src/main/resources/static/css/style.css index 98569cb..ad33dc1 100644 --- a/src/main/resources/static/css/style.css +++ b/src/main/resources/static/css/style.css @@ -28,7 +28,6 @@ body { .tabdivblurred { padding: 8px; padding-bottom: 0px; - background-color: rgba(255, 255, 255, 0.5); height: calc(100% - 42px); } @@ -109,32 +108,31 @@ body { !important; } -.WP2 { +.billing { color: black !important; - background: radial-gradient(#ffff00, #ffe169) !important; border: 1px solid darkgray; - padding-top: 8px !important; + border-radius: 16px; + padding: 4px !important; + padding-left: 8px !important; + padding-right: 8px !important; + font-weight: bolder; + font-size: smaller +} + +.WP2 { + background: radial-gradient(#ffff00, #ffe169) !important; } .WP4 { - color: black !important; background: radial-gradient(#00ffff, #69c3ff) !important; - border: 1px solid darkgray; - padding-top: 8px !important; } .WP5 { - color: black !important; background: radial-gradient(#ff0000, #e396ff) !important; - border: 1px solid darkgray; - padding-top: 8px !important; } .TA3 { - color: black !important; background: radial-gradient(#99ff99, #ccffcc) !important; - border: 1px solid darkgray; - padding-top: 8px !important; } .left { diff --git a/src/main/resources/templates/done/list.html b/src/main/resources/templates/done/list.html index bc1c970..0e6c0bd 100644 --- a/src/main/resources/templates/done/list.html +++ b/src/main/resources/templates/done/list.html @@ -6,6 +6,18 @@ Arbeitszeit +
    + +
-
Liste
+
+ + + + + + + + + + + + + + + + + + + + + +
VonBisProjektModulAufgabeAbrechnung
+
Zusammenfassung
Anhang
Kalender
-
Projekt
-
Modul
-
Tätigkeit
-
Abrechnung
+
+ + + + + + + + + + + + + +
NameBenutzt
TODO
+
+
+ + + + + + + + + + + + + +
NameBenutzt
TODO
+
+
+ + + + + + + + + + + + + +
NameBenutzt
TODO
+
+
+ + + + + + + + + + + + + + + +
NameSymbolBenutzt
TODO
+
diff --git a/src/main/resources/templates/layout/main.html b/src/main/resources/templates/layout/main.html index 17b7b92..3d396aa 100644 --- a/src/main/resources/templates/layout/main.html +++ b/src/main/resources/templates/layout/main.html @@ -38,6 +38,7 @@
  • [[${currentUser}]] abmelden
  • +