From aaee7c9dffd20df0cf8159aef80dabee5cb59929 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rg=20Henke?= Date: Thu, 15 Jan 2026 16:22:54 +0100 Subject: [PATCH] project management --- .../ProjectmanagementController.java | 45 +++++++++- .../ProjectmanagementRepository.java | 62 ++++++++++++- .../ProjectmanagementService.java | 53 ++++++++++- .../projectmanagement/model/ProjectBean.java | 31 +++++++ src/main/resources/static/css/style.css | 5 +- .../projectmanagement/dashboard.html | 20 +++-- .../projectmanagement/project/add.html | 19 ---- .../projectmanagement/project/item.html | 66 ++++++++++++++ .../projectmanagement/workpackage/item.html | 88 +++++++++++-------- .../resources/templates/public/index.html | 74 ++++++++++------ 10 files changed, 360 insertions(+), 103 deletions(-) delete mode 100644 src/main/resources/templates/projectmanagement/project/add.html create mode 100644 src/main/resources/templates/projectmanagement/project/item.html diff --git a/src/main/java/de/jottyfan/timetrack/modules/projectmanagement/ProjectmanagementController.java b/src/main/java/de/jottyfan/timetrack/modules/projectmanagement/ProjectmanagementController.java index 85a1dee..4a5c553 100644 --- a/src/main/java/de/jottyfan/timetrack/modules/projectmanagement/ProjectmanagementController.java +++ b/src/main/java/de/jottyfan/timetrack/modules/projectmanagement/ProjectmanagementController.java @@ -28,7 +28,7 @@ public class ProjectmanagementController extends CommonController { @RolesAllowed("timetrack_user") @GetMapping("/projectmanagement") public String getDashboard(final Model model) { - model.addAttribute("projects", service.getProjects()); + model.addAttribute("projects", service.getProjects(true)); return "/projectmanagement/dashboard"; } @@ -36,7 +36,16 @@ public class ProjectmanagementController extends CommonController { @GetMapping("/projectmanagement/project/add") public String getProjectAddMask(final Model model) { model.addAttribute("bean", new ProjectBean()); - return "/projectmanagement/project/add"; + model.addAttribute("funders", service.getFunders()); + return "/projectmanagement/project/item"; + } + + @RolesAllowed("timetrack_user") + @GetMapping("/projectmanagement/project/{pkProject}/edit") + public String getProjectAddMask(@PathVariable("pkProject") Integer pkProject, final Model model) { + model.addAttribute("bean", service.getProject(pkProject)); + model.addAttribute("funders", service.getFunders()); + return "/projectmanagement/project/item"; } @RolesAllowed("timetrack_user") @@ -45,6 +54,20 @@ public class ProjectmanagementController extends CommonController { model.addAttribute("bean", service.getWorkpackage(pkWorkpackage)); return "/projectmanagement/workpackage/item"; } + + @RolesAllowed("timetrack_user") + @GetMapping("/projectmanagement/workpackage/{pkWorkpackage}/delete") + public String deleteWorkpackage(@PathVariable("pkWorkpackage") Integer pkWorkpackage) { + service.deleteWorkpackage(pkWorkpackage); + return "redirect:/projectmanagement"; + } + + @RolesAllowed("timetrack_user") + @GetMapping("/projectmanagement/{pkProject}/delete") + public String deleteProject(@PathVariable("pkProject") Integer pkProject) { + service.deleteProject(pkProject); + return "redirect:/projectmanagement"; + } @RolesAllowed("timetrack_user") @GetMapping("/projectmanagement/project/{fkProject}/addWorkpackage") @@ -52,16 +75,30 @@ public class ProjectmanagementController extends CommonController { model.addAttribute("bean", WorkpackageBean.of(fkProject)); return "/projectmanagement/workpackage/item"; } + + @RolesAllowed("timetrack_user") + @PostMapping("/projectmanagement/upsert") + public String upsertWorkpackage(@ModelAttribute("bean") ProjectBean bean, BindingResult bindingResult, final Model model) { + if (bindingResult.hasErrors()) { + model.addAttribute("error", bindingResult.getAllErrors().toString()); + return "/projectmanagement"; + } + service.upsertProject(bean); + return "redirect:/projectmanagement"; + } @RolesAllowed("timetrack_user") - @PostMapping("/projectmanagement/project/{fkProject}/update") + @PostMapping("/projectmanagement/project/{fkProject}/upsert") public String updateWorkpackage(@PathVariable("fkProject") Integer fkProject, @ModelAttribute("bean") WorkpackageBean bean, BindingResult bindingResult, final Model model) { if (bindingResult.hasErrors()) { + model.addAttribute("error", bindingResult.getAllErrors().toString()); return "/projectmanagement/workpackage/item"; } bean.setFkProject(fkProject); - service.updateWorkpackage(bean); + service.upsertWorkpackage(bean); return "redirect:/projectmanagement"; } + + } diff --git a/src/main/java/de/jottyfan/timetrack/modules/projectmanagement/ProjectmanagementRepository.java b/src/main/java/de/jottyfan/timetrack/modules/projectmanagement/ProjectmanagementRepository.java index 6d59252..af494de 100644 --- a/src/main/java/de/jottyfan/timetrack/modules/projectmanagement/ProjectmanagementRepository.java +++ b/src/main/java/de/jottyfan/timetrack/modules/projectmanagement/ProjectmanagementRepository.java @@ -1,18 +1,23 @@ package de.jottyfan.timetrack.modules.projectmanagement; +import static de.jottyfan.timetrack.db.project.Tables.T_FUNDER; import static de.jottyfan.timetrack.db.project.Tables.T_PROJECT; import static de.jottyfan.timetrack.db.project.Tables.T_WORKPACKAGE; +import java.time.LocalDate; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import org.jooq.DSLContext; +import org.jooq.InsertValuesStep3; +import org.jooq.InsertValuesStep6; import org.jooq.UpdateConditionStep; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Repository; +import de.jottyfan.timetrack.db.project.tables.records.TFunderRecord; import de.jottyfan.timetrack.db.project.tables.records.TProjectRecord; import de.jottyfan.timetrack.db.project.tables.records.TWorkpackageRecord; import de.jottyfan.timetrack.modules.projectmanagement.model.ProjectBean; @@ -29,6 +34,10 @@ public class ProjectmanagementRepository { @Autowired private DSLContext jooq; + public List getFunders() { + return jooq.selectFrom(T_FUNDER).fetchInto(TFunderRecord.class); + } + public List getProjects() { List projects = jooq.selectFrom(T_PROJECT).fetchInto(TProjectRecord.class); List workpackages = jooq.selectFrom(T_WORKPACKAGE).fetchInto(TWorkpackageRecord.class); @@ -49,7 +58,8 @@ public class ProjectmanagementRepository { } public WorkpackageBean getWorkpackage(Integer pkWorkpackage) { - return jooq.selectFrom(T_WORKPACKAGE).where(T_WORKPACKAGE.PK_WORKPACKAGE.eq(pkWorkpackage)).fetchOneInto(WorkpackageBean.class); + return jooq.selectFrom(T_WORKPACKAGE).where(T_WORKPACKAGE.PK_WORKPACKAGE.eq(pkWorkpackage)) + .fetchOneInto(WorkpackageBean.class); } public void updateWorkpackage(WorkpackageBean bean) { @@ -67,4 +77,54 @@ public class ProjectmanagementRepository { sql.execute(); } + public void insertWorkpackage(WorkpackageBean bean) { + InsertValuesStep6 sql = jooq + // @formatter:off + .insertInto(T_WORKPACKAGE, + T_WORKPACKAGE.FK_PROJECT, + T_WORKPACKAGE.NAME, + T_WORKPACKAGE.DESCRIPTION, + T_WORKPACKAGE.MILESTONE_URL, + T_WORKPACKAGE.CONTRACT_URL, + T_WORKPACKAGE.PLANNED_DUEDATE) + .values(bean.getFkProject(), bean.getName(), bean.getDescription(), bean.getMilestoneUrl(), bean.getContractUrl(), bean.getPlannedDuedate()); + // @formatter:on + sql.execute(); + } + + public void deleteWorkpackage(Integer pkWorkpackage) { + jooq.deleteFrom(T_WORKPACKAGE).where(T_WORKPACKAGE.PK_WORKPACKAGE.eq(pkWorkpackage)).execute(); + } + + public void updateProject(ProjectBean bean) { + UpdateConditionStep sql = jooq + // @formatter:off + .update(T_PROJECT) + .set(T_PROJECT.FK_FUNDER, bean.getFkFunder()) + .set(T_PROJECT.NAME, bean.getName()) + .set(T_PROJECT.DESCRIPTION, bean.getDescription()) + .where(T_PROJECT.PK_PROJECT.eq(bean.getPkProject())); + // @formatter:on + sql.execute(); + } + + public void insertProject(ProjectBean bean) { + InsertValuesStep3 sql = jooq + // @formatter:off + .insertInto(T_PROJECT, + T_PROJECT.NAME, + T_PROJECT.DESCRIPTION, + T_PROJECT.FK_FUNDER) + .values(bean.getName(), bean.getDescription(), bean.getFkFunder()); + // @formatter:on + sql.execute(); + } + + public void deleteProject(Integer pkProject) { + jooq.deleteFrom(T_PROJECT).where(T_PROJECT.PK_PROJECT.eq(pkProject)).execute(); + } + + public ProjectBean getProject(Integer pkProject) { + return jooq.selectFrom(T_PROJECT).where(T_PROJECT.PK_PROJECT.eq(pkProject)).fetchOneInto(ProjectBean.class); + } } diff --git a/src/main/java/de/jottyfan/timetrack/modules/projectmanagement/ProjectmanagementService.java b/src/main/java/de/jottyfan/timetrack/modules/projectmanagement/ProjectmanagementService.java index cf59622..a338b78 100644 --- a/src/main/java/de/jottyfan/timetrack/modules/projectmanagement/ProjectmanagementService.java +++ b/src/main/java/de/jottyfan/timetrack/modules/projectmanagement/ProjectmanagementService.java @@ -1,10 +1,13 @@ package de.jottyfan.timetrack.modules.projectmanagement; +import java.util.HashMap; import java.util.List; +import java.util.Map; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; +import de.jottyfan.timetrack.db.project.tables.records.TFunderRecord; import de.jottyfan.timetrack.modules.projectmanagement.model.ProjectBean; import de.jottyfan.timetrack.modules.projectmanagement.model.WorkpackageBean; @@ -24,8 +27,17 @@ public class ProjectmanagementService { * * @return all projects */ - public List getProjects() { - return repository.getProjects(); + public List getProjects(boolean includeFunderName) { + List list = repository.getProjects(); + if (includeFunderName) { + List funders = repository.getFunders(); + Map funderMap = new HashMap<>(); + funders.forEach(f -> funderMap.put(f.getPkFunder(), f.getName())); + for (ProjectBean bean : list) { + bean.setFunderName(funderMap.get(bean.getFkFunder())); + } + } + return list; } /** @@ -43,7 +55,40 @@ public class ProjectmanagementService { * * @param bean the bean */ - public void updateWorkpackage(WorkpackageBean bean) { - repository.updateWorkpackage(bean); + public void upsertWorkpackage(WorkpackageBean bean) { + if (bean.getPkWorkpackage() == null) { + repository.insertWorkpackage(bean); + } else { + repository.updateWorkpackage(bean); + } + } + + /** + * delete the work package + * + * @param pkWorkpackage the ID of the work package + */ + public void deleteWorkpackage(Integer pkWorkpackage) { + repository.deleteWorkpackage(pkWorkpackage); + } + + public void upsertProject(ProjectBean bean) { + if (bean.getPkProject() == null) { + repository.insertProject(bean); + } else { + repository.updateProject(bean); + } + } + + public void deleteProject(Integer pkProject) { + repository.deleteProject(pkProject); + } + + public List getFunders() { + return repository.getFunders(); + } + + public ProjectBean getProject(Integer pkProject) { + return repository.getProject(pkProject); } } diff --git a/src/main/java/de/jottyfan/timetrack/modules/projectmanagement/model/ProjectBean.java b/src/main/java/de/jottyfan/timetrack/modules/projectmanagement/model/ProjectBean.java index ea05199..91415b0 100644 --- a/src/main/java/de/jottyfan/timetrack/modules/projectmanagement/model/ProjectBean.java +++ b/src/main/java/de/jottyfan/timetrack/modules/projectmanagement/model/ProjectBean.java @@ -17,6 +17,8 @@ public class ProjectBean implements Serializable { private Integer pkProject; private String name; private String description; + private Integer fkFunder; + private String funderName; private final List workpackages; public ProjectBean() { @@ -28,6 +30,7 @@ public class ProjectBean implements Serializable { bean.setPkProject(r.getPkProject()); bean.setName(r.getName()); bean.setDescription(r.getDescription()); + bean.setFkFunder(r.getFkFunder()); if (workpackages != null) { bean.getWorkpackages().addAll(workpackages); } @@ -82,4 +85,32 @@ public class ProjectBean implements Serializable { public void setPkProject(Integer pkProject) { this.pkProject = pkProject; } + + /** + * @return the funderName + */ + public String getFunderName() { + return funderName; + } + + /** + * @param funderName the funderName to set + */ + public void setFunderName(String funderName) { + this.funderName = funderName; + } + + /** + * @return the fkFunder + */ + public Integer getFkFunder() { + return fkFunder; + } + + /** + * @param fkFunder the fkFunder to set + */ + public void setFkFunder(Integer fkFunder) { + this.fkFunder = fkFunder; + } } diff --git a/src/main/resources/static/css/style.css b/src/main/resources/static/css/style.css index edc8763..11a84d9 100644 --- a/src/main/resources/static/css/style.css +++ b/src/main/resources/static/css/style.css @@ -501,6 +501,7 @@ body { } .dashboardcard { - width: 312px !important; - margin: 24px !important; + width: 312px; + margin: 8px; + padding: 0px; } \ No newline at end of file diff --git a/src/main/resources/templates/projectmanagement/dashboard.html b/src/main/resources/templates/projectmanagement/dashboard.html index b377329..2f27e81 100644 --- a/src/main/resources/templates/projectmanagement/dashboard.html +++ b/src/main/resources/templates/projectmanagement/dashboard.html @@ -13,15 +13,21 @@
-
-
-
-
- +
+
+
+ : + + edit
- Workpackage anlegen + +
-
diff --git a/src/main/resources/templates/projectmanagement/project/add.html b/src/main/resources/templates/projectmanagement/project/add.html deleted file mode 100644 index fc492fc..0000000 --- a/src/main/resources/templates/projectmanagement/project/add.html +++ /dev/null @@ -1,19 +0,0 @@ - - - -Projektmanagement - - - Projekt - -
-
- TODO: Maske zum Anlegen eines neuen Projektes -
-
- - \ No newline at end of file diff --git a/src/main/resources/templates/projectmanagement/project/item.html b/src/main/resources/templates/projectmanagement/project/item.html new file mode 100644 index 0000000..17b00dc --- /dev/null +++ b/src/main/resources/templates/projectmanagement/project/item.html @@ -0,0 +1,66 @@ + + + +Projektmanagement + + + Projekt + +
+
+
+
+
+
+
ID
+
+ +
+
Name
+
+ +
+
Beschreibung
+
+ +
+
Geldgeber
+
+ +
+
+
+ +
+
+ +
+
+
+
+
+ +
+ + \ No newline at end of file diff --git a/src/main/resources/templates/projectmanagement/workpackage/item.html b/src/main/resources/templates/projectmanagement/workpackage/item.html index 0be9d8b..a38d5a4 100644 --- a/src/main/resources/templates/projectmanagement/workpackage/item.html +++ b/src/main/resources/templates/projectmanagement/workpackage/item.html @@ -7,49 +7,63 @@ Workpackage
-
- TODO: Maske zum Anlegen eines neuen Workpackages für Projekt -
-
-
-
-
-
ID
-
- -
-
Name
-
- -
-
Beschreibung
-
- -
-
Milestone-URL
-
- -
-
Auftragsdokument
-
- -
-
geplante Fertigstellung
-
- -
-
-
- -
+
+ +
+
+
ID
+
+ +
+
Name
+
+ +
+
Beschreibung
+
+ +
+
Milestone-URL
+
+ +
+
Auftragsdokument
+
+ +
+
geplante Fertigstellung
+
+ +
+
+
+ +
+
+
- +
+ +
+
diff --git a/src/main/resources/templates/public/index.html b/src/main/resources/templates/public/index.html index 8667799..dea14da 100644 --- a/src/main/resources/templates/public/index.html +++ b/src/main/resources/templates/public/index.html @@ -1,44 +1,60 @@ - + - Timetrack +Timetrack
-
- -
-
+
+
+ +
-
Start:
-
-
Ende:
-
-
Arbeitszeit total:
-
-
Pausezeit total:
-
-
Überstunden:
-
+
+ Start: +
+
+ +
+
+ Ende: +
+
+ +
+
+ Arbeitszeit total: +
+
+ +
+
+ Pausezeit total: +
+
+ +
+
+ Überstunden: +
+
+ +
-
-