show work times
This commit is contained in:
@ -1,20 +1,239 @@
|
|||||||
package de.jottyfan.timetrack.spring.done;
|
package de.jottyfan.timetrack.spring.done;
|
||||||
|
|
||||||
import java.io.Serializable;
|
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
|
* @author henkej
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public class DoneBean implements Serializable, Comparable<DoneBean>{
|
public class DoneBean implements Serializable, Comparable<DoneBean> {
|
||||||
|
|
||||||
private static final long serialVersionUID = 1L;
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
@Override
|
private static final DateTimeFormatter hhmm = DateTimeFormatter.ofPattern("HH:mm");
|
||||||
public int compareTo(DoneBean bean) {
|
|
||||||
// TODO: implement
|
private Integer pk;
|
||||||
return 0;
|
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<Integer, TProjectRecord> projectMap, Map<Integer, TModuleRecord> moduleMap,
|
||||||
|
Map<Integer, TJobRecord> jobMap, Map<Integer, TBillingRecord> 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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -11,6 +11,7 @@ import org.springframework.beans.factory.annotation.Autowired;
|
|||||||
import org.springframework.stereotype.Controller;
|
import org.springframework.stereotype.Controller;
|
||||||
import org.springframework.ui.Model;
|
import org.springframework.ui.Model;
|
||||||
import org.springframework.web.bind.annotation.GetMapping;
|
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.PathVariable;
|
||||||
import org.springframework.web.bind.annotation.RequestMapping;
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
import org.springframework.web.bind.annotation.RequestMethod;
|
import org.springframework.web.bind.annotation.RequestMethod;
|
||||||
@ -36,9 +37,15 @@ public class DoneController {
|
|||||||
|
|
||||||
@RolesAllowed("timetrack_user")
|
@RolesAllowed("timetrack_user")
|
||||||
@RequestMapping(value = "/done/list")
|
@RequestMapping(value = "/done/list")
|
||||||
public String getList(Model model) {
|
public String getList(@ModelAttribute DoneModel doneModel, Model model) {
|
||||||
List<DoneBean> list = doneService.getList();
|
String username = doneService.getCurrentUser(request);
|
||||||
|
List<DoneBean> list = doneService.getList(doneModel.getDay(), username);
|
||||||
model.addAttribute("doneList", list);
|
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";
|
return "done/list";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
@ -1,18 +1,32 @@
|
|||||||
package de.jottyfan.timetrack.spring.done;
|
package de.jottyfan.timetrack.spring.done;
|
||||||
|
|
||||||
|
import java.time.LocalDate;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import javax.servlet.http.HttpServletRequest;
|
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
|
* @author henkej
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public interface IDoneService {
|
public interface IDoneService {
|
||||||
public List<DoneBean> getList();
|
public List<DoneBean> getList(LocalDate day, String username);
|
||||||
|
|
||||||
public DoneBean getBean(Integer id);
|
public DoneBean getBean(Integer id);
|
||||||
|
|
||||||
public String getCurrentUser(HttpServletRequest request);
|
public String getCurrentUser(HttpServletRequest request);
|
||||||
|
|
||||||
|
public List<TProjectRecord> getProjects();
|
||||||
|
|
||||||
|
public List<TModuleRecord> getModules();
|
||||||
|
|
||||||
|
public List<TJobRecord> getJobs();
|
||||||
|
|
||||||
|
public List<TBillingRecord> getBillings();
|
||||||
}
|
}
|
||||||
|
@ -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<TLoginRecord> 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<TProjectRecord> 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<TModuleRecord> 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<TJobRecord> 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<TBillingRecord> 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<Integer, TProjectRecord> getProjectMap()
|
||||||
|
throws DataAccessException, ClassNotFoundException, SQLException {
|
||||||
|
Map<Integer, TProjectRecord> 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<Integer, TModuleRecord> getModuleMap() throws DataAccessException, ClassNotFoundException, SQLException {
|
||||||
|
Map<Integer, TModuleRecord> 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<Integer, TJobRecord> getJobMap() throws DataAccessException, ClassNotFoundException, SQLException {
|
||||||
|
Map<Integer, TJobRecord> 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<Integer, TBillingRecord> getBillingMap()
|
||||||
|
throws DataAccessException, ClassNotFoundException, SQLException {
|
||||||
|
Map<Integer, TBillingRecord> 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<DoneBean> getAllOfDay(LocalDate day, 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,
|
||||||
|
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<DoneBean> list = new ArrayList<>();
|
||||||
|
Map<Integer, TProjectRecord> projectMap = getProjectMap();
|
||||||
|
Map<Integer, TModuleRecord> moduleMap = getModuleMap();
|
||||||
|
Map<Integer, TJobRecord> jobMap = getJobMap();
|
||||||
|
Map<Integer, TBillingRecord> billingMap = getBillingMap();
|
||||||
|
for (Record7<Integer, LocalDateTime, LocalDateTime, Integer, Integer, Integer, Integer> 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<TDoneRecord> sql = getJooq()
|
||||||
|
// @formatter:off
|
||||||
|
.deleteFrom(T_DONE)
|
||||||
|
.where(T_DONE.PK.eq(pk));
|
||||||
|
// @formatter:on
|
||||||
|
LOGGER.debug("{}", sql.toString());
|
||||||
|
return sql.execute();
|
||||||
|
}
|
||||||
|
}
|
@ -1,5 +1,6 @@
|
|||||||
package de.jottyfan.timetrack.spring.done.impl;
|
package de.jottyfan.timetrack.spring.done.impl;
|
||||||
|
|
||||||
|
import java.time.LocalDate;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
@ -13,10 +14,12 @@ import org.springframework.beans.factory.annotation.Autowired;
|
|||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
import org.springframework.transaction.annotation.Transactional;
|
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.DoneBean;
|
||||||
import de.jottyfan.timetrack.spring.done.IDoneService;
|
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;
|
import de.jottyfan.timetrack.spring.note.impl.NoteService;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -33,19 +36,25 @@ public class DoneService implements IDoneService {
|
|||||||
private DSLContext dsl;
|
private DSLContext dsl;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getCurrentUser(HttpServletRequest request) {
|
public String getCurrentUser(HttpServletRequest request) {
|
||||||
KeycloakSecurityContext ksc = (KeycloakSecurityContext) request.getAttribute(KeycloakSecurityContext.class.getName());
|
KeycloakSecurityContext ksc = (KeycloakSecurityContext) request
|
||||||
|
.getAttribute(KeycloakSecurityContext.class.getName());
|
||||||
return ksc == null ? "" : ksc.getIdToken().getPreferredUsername();
|
return ksc == null ? "" : ksc.getIdToken().getPreferredUsername();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<DoneBean> getList() {
|
public List<DoneBean> getList(LocalDate day, String username) {
|
||||||
// try {
|
try {
|
||||||
// return new DoneGateway(dsl).getAll();
|
DoneGateway gw = new DoneGateway(dsl);
|
||||||
// } catch (Exception e) {
|
Integer userId = gw.getUserId(username);
|
||||||
// LOGGER.error(e);
|
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<>();
|
return new ArrayList<>();
|
||||||
// }
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -54,4 +63,44 @@ public class DoneService implements IDoneService {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<TProjectRecord> getProjects() {
|
||||||
|
try {
|
||||||
|
return new DoneGateway(dsl).getAllProjects();
|
||||||
|
} catch (Exception e) {
|
||||||
|
LOGGER.error(e);
|
||||||
|
return new ArrayList<>();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<TModuleRecord> getModules() {
|
||||||
|
try {
|
||||||
|
return new DoneGateway(dsl).getAllModules();
|
||||||
|
} catch (Exception e) {
|
||||||
|
LOGGER.error(e);
|
||||||
|
return new ArrayList<>();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<TJobRecord> getJobs() {
|
||||||
|
try {
|
||||||
|
return new DoneGateway(dsl).getAllJobs();
|
||||||
|
} catch (Exception e) {
|
||||||
|
LOGGER.error(e);
|
||||||
|
return new ArrayList<>();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<TBillingRecord> getBillings() {
|
||||||
|
try {
|
||||||
|
return new DoneGateway(dsl).getAllBillings();
|
||||||
|
} catch (Exception e) {
|
||||||
|
LOGGER.error(e);
|
||||||
|
return new ArrayList<>();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -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<DoneBean> {
|
|
||||||
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<Integer, TProjectRecord> projectMap, Map<Integer, TModuleRecord> moduleMap,
|
|
||||||
Map<Integer, TJobRecord> jobMap, Map<Integer, TBillingRecord> 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;
|
|
||||||
}
|
|
||||||
}
|
|
@ -28,7 +28,6 @@ body {
|
|||||||
.tabdivblurred {
|
.tabdivblurred {
|
||||||
padding: 8px;
|
padding: 8px;
|
||||||
padding-bottom: 0px;
|
padding-bottom: 0px;
|
||||||
background-color: rgba(255, 255, 255, 0.5);
|
|
||||||
height: calc(100% - 42px);
|
height: calc(100% - 42px);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -109,32 +108,31 @@ body {
|
|||||||
!important;
|
!important;
|
||||||
}
|
}
|
||||||
|
|
||||||
.WP2 {
|
.billing {
|
||||||
color: black !important;
|
color: black !important;
|
||||||
background: radial-gradient(#ffff00, #ffe169) !important;
|
|
||||||
border: 1px solid darkgray;
|
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 {
|
.WP4 {
|
||||||
color: black !important;
|
|
||||||
background: radial-gradient(#00ffff, #69c3ff) !important;
|
background: radial-gradient(#00ffff, #69c3ff) !important;
|
||||||
border: 1px solid darkgray;
|
|
||||||
padding-top: 8px !important;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.WP5 {
|
.WP5 {
|
||||||
color: black !important;
|
|
||||||
background: radial-gradient(#ff0000, #e396ff) !important;
|
background: radial-gradient(#ff0000, #e396ff) !important;
|
||||||
border: 1px solid darkgray;
|
|
||||||
padding-top: 8px !important;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.TA3 {
|
.TA3 {
|
||||||
color: black !important;
|
|
||||||
background: radial-gradient(#99ff99, #ccffcc) !important;
|
background: radial-gradient(#99ff99, #ccffcc) !important;
|
||||||
border: 1px solid darkgray;
|
|
||||||
padding-top: 8px !important;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.left {
|
.left {
|
||||||
|
@ -6,6 +6,18 @@
|
|||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<font layout:fragment="title">Arbeitszeit</font>
|
<font layout:fragment="title">Arbeitszeit</font>
|
||||||
|
<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="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>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
<ul layout:fragment="menu">
|
<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" th:href="@{/done/add}">Neuer
|
||||||
Eintrag</a></li>
|
Eintrag</a></li>
|
||||||
@ -18,18 +30,104 @@
|
|||||||
<li class="nav-item"><a class="nav-link navlinkstyle" data-bs-toggle="tab" href="#div_calendar">Kalender</a></li>
|
<li class="nav-item"><a class="nav-link navlinkstyle" data-bs-toggle="tab" href="#div_calendar">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_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_module">Modul</a></li>
|
||||||
<li class="nav-item"><a class="nav-link navlinkstyle" data-bs-toggle="tab" href="#div_job">Tätigkeit</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_budget">Abrechnung</a></li>
|
<li class="nav-item"><a class="nav-link navlinkstyle" data-bs-toggle="tab" href="#div_billing">Abrechnung</a></li>
|
||||||
</ul>
|
</ul>
|
||||||
<div class="tabdivblurred tab-content">
|
<div class="tabdivblurred tab-content">
|
||||||
<div id="div_list" class="tab-pane active">Liste</div>
|
<div id="div_list" class="tab-pane active" style="background-color: white">
|
||||||
|
<table class="table table-striped table-condensed">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>Von</th>
|
||||||
|
<th>Bis</th>
|
||||||
|
<th>Projekt</th>
|
||||||
|
<th>Modul</th>
|
||||||
|
<th>Aufgabe</th>
|
||||||
|
<th>Abrechnung</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<tr th:each="done : ${doneList}">
|
||||||
|
<td><span th:text="${#temporals.format(done.timeFrom, 'HH:mm')}"></span></td>
|
||||||
|
<td><span th:text="${#temporals.format(done.timeUntil, 'HH:mm')}"></span></td>
|
||||||
|
<td><span th:text="${done.project.name}"></span></td>
|
||||||
|
<td><span th:text="${done.module.name}"></span></td>
|
||||||
|
<td><span th:text="${done.activity.name}"></span></td>
|
||||||
|
<td><span th:text="${done.billing.shortcut}" th:class="'billing ' + ${done.billing.csskey}"
|
||||||
|
th:if="${done.billing != null}"></span></td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
<div id="div_summary" class="tab-pane fade">Zusammenfassung</div>
|
<div id="div_summary" class="tab-pane fade">Zusammenfassung</div>
|
||||||
<div id="div_attachment" class="tab-pane fade">Anhang</div>
|
<div id="div_attachment" class="tab-pane fade">Anhang</div>
|
||||||
<div id="div_calendar" class="tab-pane fade">Kalender</div>
|
<div id="div_calendar" class="tab-pane fade">Kalender</div>
|
||||||
<div id="div_project" class="tab-pane fade">Projekt</div>
|
<div id="div_project" class="tab-pane fade" style="background-color: white">
|
||||||
<div id="div_module" class="tab-pane fade">Modul</div>
|
<table class="table table-striped table-condensed">
|
||||||
<div id="div_job" class="tab-pane fade">Tätigkeit</div>
|
<thead>
|
||||||
<div id="div_budget" class="tab-pane fade">Abrechnung</div>
|
<tr>
|
||||||
|
<th>Name</th>
|
||||||
|
<th>Benutzt</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<tr th:each="project : ${projectList}">
|
||||||
|
<td><span th:text="${project.name}"></span></td>
|
||||||
|
<td>TODO</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
<div id="div_module" class="tab-pane fade" style="background-color: white">
|
||||||
|
<table class="table table-striped table-condensed">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>Name</th>
|
||||||
|
<th>Benutzt</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<tr th:each="module : ${moduleList}">
|
||||||
|
<td><span th:text="${module.name}"></span></td>
|
||||||
|
<td>TODO</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
<div id="div_job" class="tab-pane fade" style="background-color: white">
|
||||||
|
<table class="table table-striped table-condensed">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>Name</th>
|
||||||
|
<th>Benutzt</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<tr th:each="job : ${jobList}">
|
||||||
|
<td><span th:text="${job.name}"></span></td>
|
||||||
|
<td>TODO</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
<div id="div_billing" class="tab-pane fade" style="background-color: white">
|
||||||
|
<table class="table table-striped table-condensed">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>Name</th>
|
||||||
|
<th>Symbol</th>
|
||||||
|
<th>Benutzt</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>TODO</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</main>
|
</main>
|
||||||
</body>
|
</body>
|
||||||
|
@ -38,6 +38,7 @@
|
|||||||
<li><a class="dropdown-item" th:href="@{/logout}">[[${currentUser}]] abmelden</a></li>
|
<li><a class="dropdown-item" th:href="@{/logout}">[[${currentUser}]] abmelden</a></li>
|
||||||
</ul></li>
|
</ul></li>
|
||||||
<li class="nav-item"><a class="nav-link titlemod"><font layout:fragment="title"></font></a></li>
|
<li class="nav-item"><a class="nav-link titlemod"><font layout:fragment="title"></font></a></li>
|
||||||
|
<li layout:fragment="menuitem" style="list-style-type: none"></li>
|
||||||
<li layout:fragment="menu" style="list-style-type: none"></li>
|
<li layout:fragment="menu" style="list-style-type: none"></li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
|
Reference in New Issue
Block a user