issue-25 #27
@ -4,11 +4,13 @@
|
||||
<option name="autoReloadType" value="SELECTIVE" />
|
||||
</component>
|
||||
<component name="ChangeListManager">
|
||||
<list default="true" id="3a869f59-290a-4ab2-b036-a878ce801bc4" name="Changes" comment="Removed unused TaskgroupShortInfo.java">
|
||||
<list default="true" id="3a869f59-290a-4ab2-b036-a878ce801bc4" name="Changes" comment="Load worked minutes when reloading dashboard">
|
||||
<change afterPath="$PROJECT_DIR$/src/main/java/core/api/models/timemanager/taskSchedule/ScheduleStatus.java" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/.idea/workspace.xml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/workspace.xml" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/src/main/java/core/api/controller/ScheduleController.java" beforeDir="false" afterPath="$PROJECT_DIR$/src/main/java/core/api/controller/ScheduleController.java" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/src/main/java/core/api/models/timemanager/taskSchedule/ActiveMinutesInformation.java" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/src/main/java/core/repositories/timemanager/BasicTaskScheduleRepository.java" beforeDir="false" afterPath="$PROJECT_DIR$/src/main/java/core/repositories/timemanager/BasicTaskScheduleRepository.java" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/src/main/java/core/services/TaskScheduleService.java" beforeDir="false" afterPath="$PROJECT_DIR$/src/main/java/core/services/TaskScheduleService.java" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/src/main/java/core/services/TaskService.java" beforeDir="false" afterPath="$PROJECT_DIR$/src/main/java/core/services/TaskService.java" afterDir="false" />
|
||||
</list>
|
||||
<option name="SHOW_DIALOG" value="false" />
|
||||
<option name="HIGHLIGHT_CONFLICTS" value="true" />
|
||||
@ -60,7 +62,9 @@
|
||||
"node.js.detected.package.tslint": "true",
|
||||
"node.js.selected.package.eslint": "(autodetect)",
|
||||
"node.js.selected.package.tslint": "(autodetect)",
|
||||
"nodejs_package_manager_path": "npm",
|
||||
"settings.editor.selected.configurable": "swagger",
|
||||
"ts.external.directory.path": "/snap/intellij-idea-ultimate/459/plugins/javascript-impl/jsLanguageServicesImpl/external",
|
||||
"vue.rearranger.settings.migration": "true"
|
||||
},
|
||||
"keyToStringList": {
|
||||
@ -99,7 +103,11 @@
|
||||
<workItem from="1698067098771" duration="4770000" />
|
||||
<workItem from="1698127431684" duration="2039000" />
|
||||
<workItem from="1698164397550" duration="2329000" />
|
||||
<workItem from="1698246651541" duration="766000" />
|
||||
<workItem from="1698246651541" duration="5106000" />
|
||||
<workItem from="1698298897364" duration="4242000" />
|
||||
<workItem from="1698426430946" duration="665000" />
|
||||
<workItem from="1698474363766" duration="3686000" />
|
||||
<workItem from="1698499063683" duration="7685000" />
|
||||
</task>
|
||||
<task id="LOCAL-00001" summary="Structure Taskgroups in Hierarchies">
|
||||
<option name="closed" value="true" />
|
||||
@ -165,7 +173,71 @@
|
||||
<option name="project" value="LOCAL" />
|
||||
<updated>1698168406655</updated>
|
||||
</task>
|
||||
<option name="localTasksCounter" value="9" />
|
||||
<task id="LOCAL-00009" summary="Fix Foreign Key Constraint Fail when deleting Taskgroups">
|
||||
<option name="closed" value="true" />
|
||||
<created>1698247531000</created>
|
||||
<option name="number" value="00009" />
|
||||
<option name="presentableId" value="LOCAL-00009" />
|
||||
<option name="project" value="LOCAL" />
|
||||
<updated>1698247531000</updated>
|
||||
</task>
|
||||
<task id="LOCAL-00010" summary="Stop and Finish TaskSchedules">
|
||||
<option name="closed" value="true" />
|
||||
<created>1698306038382</created>
|
||||
<option name="number" value="00010" />
|
||||
<option name="presentableId" value="LOCAL-00010" />
|
||||
<option name="project" value="LOCAL" />
|
||||
<updated>1698306038383</updated>
|
||||
</task>
|
||||
<task id="LOCAL-00011" summary="Include TaskScheduleStopResponse">
|
||||
<option name="closed" value="true" />
|
||||
<created>1698306056254</created>
|
||||
<option name="number" value="00011" />
|
||||
<option name="presentableId" value="LOCAL-00011" />
|
||||
<option name="project" value="LOCAL" />
|
||||
<updated>1698306056254</updated>
|
||||
</task>
|
||||
<task id="LOCAL-00012" summary="Fix starting schedule and returning active time of schedule after stop">
|
||||
<option name="closed" value="true" />
|
||||
<created>1698306442833</created>
|
||||
<option name="number" value="00012" />
|
||||
<option name="presentableId" value="LOCAL-00012" />
|
||||
<option name="project" value="LOCAL" />
|
||||
<updated>1698306442833</updated>
|
||||
</task>
|
||||
<task id="LOCAL-00013" summary="Remove update spamming in console">
|
||||
<option name="closed" value="true" />
|
||||
<created>1698306889808</created>
|
||||
<option name="number" value="00013" />
|
||||
<option name="presentableId" value="LOCAL-00013" />
|
||||
<option name="project" value="LOCAL" />
|
||||
<updated>1698306889808</updated>
|
||||
</task>
|
||||
<task id="LOCAL-00014" summary="Start task now from Taskoverview in Dashboard">
|
||||
<option name="closed" value="true" />
|
||||
<created>1698500028161</created>
|
||||
<option name="number" value="00014" />
|
||||
<option name="presentableId" value="LOCAL-00014" />
|
||||
<option name="project" value="LOCAL" />
|
||||
<updated>1698500028161</updated>
|
||||
</task>
|
||||
<task id="LOCAL-00015" summary="Load worked minutes when reloading dashboard">
|
||||
<option name="closed" value="true" />
|
||||
<created>1698512058945</created>
|
||||
<option name="number" value="00015" />
|
||||
<option name="presentableId" value="LOCAL-00015" />
|
||||
<option name="project" value="LOCAL" />
|
||||
<updated>1698512058945</updated>
|
||||
</task>
|
||||
<task id="LOCAL-00016" summary="Load worked minutes when reloading dashboard">
|
||||
<option name="closed" value="true" />
|
||||
<created>1698512069065</created>
|
||||
<option name="number" value="00016" />
|
||||
<option name="presentableId" value="LOCAL-00016" />
|
||||
<option name="project" value="LOCAL" />
|
||||
<updated>1698512069065</updated>
|
||||
</task>
|
||||
<option name="localTasksCounter" value="17" />
|
||||
<servers />
|
||||
</component>
|
||||
<component name="TypeScriptGeneratedFilesManager">
|
||||
@ -182,7 +254,14 @@
|
||||
<MESSAGE value="Delete Schedules" />
|
||||
<MESSAGE value="Deliver Schedule Path Info when fetching Schedules" />
|
||||
<MESSAGE value="Removed unused TaskgroupShortInfo.java" />
|
||||
<option name="LAST_COMMIT_MESSAGE" value="Removed unused TaskgroupShortInfo.java" />
|
||||
<MESSAGE value="Fix Foreign Key Constraint Fail when deleting Taskgroups" />
|
||||
<MESSAGE value="Stop and Finish TaskSchedules" />
|
||||
<MESSAGE value="Include TaskScheduleStopResponse" />
|
||||
<MESSAGE value="Fix starting schedule and returning active time of schedule after stop" />
|
||||
<MESSAGE value="Remove update spamming in console" />
|
||||
<MESSAGE value="Start task now from Taskoverview in Dashboard" />
|
||||
<MESSAGE value="Load worked minutes when reloading dashboard" />
|
||||
<option name="LAST_COMMIT_MESSAGE" value="Load worked minutes when reloading dashboard" />
|
||||
</component>
|
||||
<component name="XDebuggerManager">
|
||||
<breakpoint-manager>
|
||||
@ -192,11 +271,6 @@
|
||||
<line>52</line>
|
||||
<option name="timeStamp" value="1" />
|
||||
</line-breakpoint>
|
||||
<line-breakpoint enabled="true" type="java-line">
|
||||
<url>file://$PROJECT_DIR$/src/main/java/core/api/controller/ScheduleController.java</url>
|
||||
<line>41</line>
|
||||
<option name="timeStamp" value="2" />
|
||||
</line-breakpoint>
|
||||
</breakpoints>
|
||||
</breakpoint-manager>
|
||||
</component>
|
||||
|
@ -1,12 +1,12 @@
|
||||
package core.api.controller;
|
||||
|
||||
import core.api.models.auth.SimpleStatusResponse;
|
||||
import core.api.models.timemanager.taskSchedule.BasicTaskScheduleEntityInfo;
|
||||
import core.api.models.timemanager.taskSchedule.BasicTaskScheduleFieldInfo;
|
||||
import core.api.models.timemanager.taskSchedule.ScheduleInfo;
|
||||
import core.api.models.timemanager.taskSchedule.*;
|
||||
import core.entities.User;
|
||||
import core.entities.timemanager.BasicTaskSchedule;
|
||||
import core.entities.timemanager.ScheduleType;
|
||||
import core.entities.timemanager.Task;
|
||||
import core.repositories.UserRepository;
|
||||
import core.repositories.timemanager.BasicTaskScheduleRepository;
|
||||
import core.services.*;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
@ -15,9 +15,7 @@ import org.springframework.security.core.context.SecurityContextHolder;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import javax.validation.Valid;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
import java.util.*;
|
||||
|
||||
@CrossOrigin(origins = "*", maxAge = 3600)
|
||||
@RestController
|
||||
@ -27,12 +25,15 @@ public class ScheduleController {
|
||||
private final TaskService taskService;
|
||||
private final TaskScheduleService taskScheduleService;
|
||||
private final BasicTaskScheduleRepository basicTaskScheduleRepository;
|
||||
private final UserRepository userRepository;
|
||||
|
||||
public ScheduleController(@Autowired TaskService taskService, @Autowired TaskScheduleService taskScheduleService,
|
||||
BasicTaskScheduleRepository basicTaskScheduleRepository) {
|
||||
BasicTaskScheduleRepository basicTaskScheduleRepository,
|
||||
UserRepository userRepository) {
|
||||
this.taskService = taskService;
|
||||
this.taskScheduleService = taskScheduleService;
|
||||
this.basicTaskScheduleRepository = basicTaskScheduleRepository;
|
||||
this.userRepository = userRepository;
|
||||
}
|
||||
|
||||
@GetMapping("/schedules/{taskID}/{scheduleType}")
|
||||
@ -102,9 +103,9 @@ public class ScheduleController {
|
||||
return ResponseEntity.ok(new SimpleStatusResponse("success"));
|
||||
}
|
||||
|
||||
@GetMapping("/schedules/today")
|
||||
public ResponseEntity<?> loadTodaysSchedules() {
|
||||
ServiceResult<List<BasicTaskSchedule>> todaysSchedules = taskScheduleService.loadTodaysSchedule(SecurityContextHolder.getContext().getAuthentication().getName());
|
||||
@GetMapping("/schedules/today/{activateable}")
|
||||
public ResponseEntity<?> loadTodaysSchedules(@PathVariable boolean activateable) {
|
||||
ServiceResult<List<BasicTaskSchedule>> todaysSchedules = taskScheduleService.loadTodaysSchedule(SecurityContextHolder.getContext().getAuthentication().getName(), activateable);
|
||||
if(todaysSchedules.getExitCode() == ServiceExitCode.MISSING_ENTITY) {
|
||||
return ResponseEntity.status(403).body(new SimpleStatusResponse("failed"));
|
||||
} else {
|
||||
@ -136,7 +137,68 @@ public class ScheduleController {
|
||||
if(scheduleResult.getExitCode() == ServiceExitCode.ENTITY_ALREADY_EXIST) {
|
||||
return ResponseEntity.status(409).body(new SimpleStatusResponse("failed"));
|
||||
} else {
|
||||
return ResponseEntity.ok(new BasicTaskScheduleEntityInfo(scheduleResult.getResult()));
|
||||
return ResponseEntity.ok(new ScheduleInfo(scheduleResult.getResult()));
|
||||
}
|
||||
}
|
||||
|
||||
@GetMapping("/schedules/active")
|
||||
public ResponseEntity<?> getActiveSchedule() {
|
||||
ServiceResult<BasicTaskSchedule> activeScheduleResult = taskScheduleService.getActiveSchedule(SecurityContextHolder.getContext().getAuthentication().getName());
|
||||
if(activeScheduleResult.getExitCode() == ServiceExitCode.MISSING_ENTITY) {
|
||||
return ResponseEntity.ok(new ScheduleInfo());
|
||||
} else {
|
||||
return ResponseEntity.ok(new ScheduleInfo(activeScheduleResult.getResult()));
|
||||
}
|
||||
}
|
||||
|
||||
@PostMapping("/schedules/{scheduleID}/activate")
|
||||
public ResponseEntity<?> activateSchedule(@PathVariable long scheduleID) {
|
||||
PermissionResult<BasicTaskSchedule> schedulePermissionResult = taskScheduleService.getSchedulePermissions(scheduleID, SecurityContextHolder.getContext().getAuthentication().getName());
|
||||
if(!schedulePermissionResult.isHasPermissions()) {
|
||||
return ResponseEntity.status(403).body(new SimpleStatusResponse("failed"));
|
||||
}
|
||||
|
||||
if(schedulePermissionResult.getExitCode() == ServiceExitCode.MISSING_ENTITY) {
|
||||
return ResponseEntity.status(404).body(new SimpleStatusResponse("failed"));
|
||||
}
|
||||
|
||||
ServiceResult<BasicTaskSchedule> scheduleActivateResult = taskScheduleService.activateSchedule(schedulePermissionResult.getResult());
|
||||
if(scheduleActivateResult.getExitCode() == ServiceExitCode.ENTITY_ALREADY_EXIST) {
|
||||
return ResponseEntity.status(409).body(new SimpleStatusResponse("failed"));
|
||||
} else if(scheduleActivateResult.getExitCode() == ServiceExitCode.OK){
|
||||
return ResponseEntity.ok(new ScheduleActivateInfo(scheduleActivateResult.getResult().getStartTime()));
|
||||
} else {
|
||||
return ResponseEntity.status(404).body(new SimpleStatusResponse("failed"));
|
||||
}
|
||||
}
|
||||
|
||||
@PostMapping("/schedules/{scheduleID}/stop/{finish}")
|
||||
public ResponseEntity<?> stopSchedule(@PathVariable long scheduleID, @PathVariable boolean finish) {
|
||||
PermissionResult<BasicTaskSchedule> schedulePermissionResult = taskScheduleService.getSchedulePermissions(scheduleID, SecurityContextHolder.getContext().getAuthentication().getName());
|
||||
if(!schedulePermissionResult.isHasPermissions()) {
|
||||
return ResponseEntity.status(403).body(new SimpleStatusResponse("failed"));
|
||||
}
|
||||
|
||||
if(schedulePermissionResult.getExitCode() == ServiceExitCode.MISSING_ENTITY) {
|
||||
return ResponseEntity.status(404).body(new SimpleStatusResponse("failed"));
|
||||
}
|
||||
|
||||
ServiceResult<Integer> stopResult = taskScheduleService.stopSchedule(schedulePermissionResult.getResult(), finish);
|
||||
if(stopResult.getExitCode() == ServiceExitCode.INVALID_OPERATION) {
|
||||
return ResponseEntity.status(400).body(new SimpleStatusResponse("failed"));
|
||||
} else {
|
||||
return ResponseEntity.ok(new TaskScheduleStopResponse(stopResult.getResult()));
|
||||
}
|
||||
}
|
||||
|
||||
@GetMapping("/schedules/status/today")
|
||||
public ResponseEntity<?> getWorkedMinutesToday() {
|
||||
Optional<User> user = userRepository.findByUsername(SecurityContextHolder.getContext().getAuthentication().getName());
|
||||
if(user.isEmpty()) {
|
||||
return ResponseEntity.status(404).body(new SimpleStatusResponse("failed"));
|
||||
}
|
||||
|
||||
int workedMinutes = taskScheduleService.getWorkedMinutes(user.get());
|
||||
return ResponseEntity.ok(new ScheduleStatus(workedMinutes, taskScheduleService.isAnyScheduleMissed(user.get())));
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,7 @@
|
||||
package core.api.controller;
|
||||
|
||||
import core.api.models.auth.SimpleStatusResponse;
|
||||
import core.api.models.timemanager.taskSchedule.ScheduleInfo;
|
||||
import core.api.models.timemanager.tasks.TaskEntityInfo;
|
||||
import core.api.models.timemanager.tasks.TaskFieldInfo;
|
||||
import core.entities.timemanager.Task;
|
||||
@ -110,4 +111,19 @@ public class TaskController {
|
||||
|
||||
return ResponseEntity.ok(new TaskEntityInfo(taskPermissionResult.getResult()));
|
||||
}
|
||||
|
||||
@PostMapping("/tasks/{taskID}/finish")
|
||||
public ResponseEntity<?> finishTask(@PathVariable long taskID) {
|
||||
PermissionResult<Task> taskPermissionResult = taskService.getTaskPermissions(taskID, SecurityContextHolder.getContext().getAuthentication().getName());
|
||||
if (!taskPermissionResult.isHasPermissions()) {
|
||||
return ResponseEntity.status(403).body(new SimpleStatusResponse("failed"));
|
||||
}
|
||||
|
||||
if (taskPermissionResult.getExitCode() == ServiceExitCode.MISSING_ENTITY) {
|
||||
return ResponseEntity.status(404).body(new SimpleStatusResponse("failed"));
|
||||
}
|
||||
|
||||
taskService.finishTask(taskPermissionResult.getResult());
|
||||
return ResponseEntity.ok(new SimpleStatusResponse("success"));
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,7 @@
|
||||
package core.api.controller;
|
||||
|
||||
import core.api.models.auth.SimpleStatusResponse;
|
||||
import core.api.models.timemanager.taskgroup.RecursiveTaskgroupInfo;
|
||||
import core.api.models.timemanager.taskgroup.TaskgroupDetailInfo;
|
||||
import core.api.models.timemanager.taskgroup.TaskgroupEntityInfo;
|
||||
import core.api.models.timemanager.taskgroup.TaskgroupFieldInfo;
|
||||
@ -80,6 +81,13 @@ public class TaskgroupController {
|
||||
return ResponseEntity.ok(taskgroupEntityInfos);
|
||||
}
|
||||
|
||||
@GetMapping("/taskgroups/tree")
|
||||
public ResponseEntity<List<RecursiveTaskgroupInfo>> listTaskgroupsOfUserAsTree() {
|
||||
List<Taskgroup> taskgroups = taskgroupService.getTopTaskgroupsByUser(SecurityContextHolder.getContext().getAuthentication().getName());
|
||||
List<RecursiveTaskgroupInfo> taskgroupEntityInfos = taskgroups.stream().map(RecursiveTaskgroupInfo::new).toList();
|
||||
return ResponseEntity.ok(taskgroupEntityInfos);
|
||||
}
|
||||
|
||||
@GetMapping("/taskgroups/{taskgroupID}")
|
||||
public ResponseEntity<?> getDetails(@PathVariable long taskgroupID) {
|
||||
PermissionResult<Taskgroup> taskgroupPermissionResult = taskgroupService.getTaskgroupByIDAndUsername(taskgroupID, SecurityContextHolder.getContext().getAuthentication().getName());
|
||||
|
@ -0,0 +1,21 @@
|
||||
package core.api.models.timemanager.taskSchedule;
|
||||
|
||||
import java.time.LocalDate;
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
public class ScheduleActivateInfo {
|
||||
|
||||
private LocalDateTime startTime;
|
||||
|
||||
public ScheduleActivateInfo(LocalDateTime startTime) {
|
||||
this.startTime = startTime;
|
||||
}
|
||||
|
||||
public LocalDateTime getStartTime() {
|
||||
return startTime;
|
||||
}
|
||||
|
||||
public void setStartTime(LocalDateTime startTime) {
|
||||
this.startTime = startTime;
|
||||
}
|
||||
}
|
@ -32,7 +32,7 @@ public class ScheduleInfo {
|
||||
this.finishTime = basicTaskSchedule.getFinishedTime();
|
||||
|
||||
if(this.finishTime == null && this.startTime != null) {
|
||||
this.activeMinutes = (int) Duration.between(basicTaskSchedule.getStartTime(), LocalDate.now()).toMinutes();
|
||||
this.activeMinutes = (int) Duration.between(basicTaskSchedule.getStartTime(), LocalDateTime.now()).toMinutes();
|
||||
} else if(this.startTime != null){
|
||||
this.activeMinutes = (int) Duration.between(basicTaskSchedule.getStartTime(), basicTaskSchedule.getFinishedTime()).toMinutes();
|
||||
}
|
||||
@ -44,6 +44,10 @@ public class ScheduleInfo {
|
||||
this.taskgroupPath = taskgroupPath.stream().map(TaskgroupEntityInfo::new).toList();
|
||||
}
|
||||
|
||||
public ScheduleInfo() {
|
||||
this.scheduleID = -1;
|
||||
}
|
||||
|
||||
public long getScheduleID() {
|
||||
return scheduleID;
|
||||
}
|
||||
|
@ -0,0 +1,28 @@
|
||||
package core.api.models.timemanager.taskSchedule;
|
||||
|
||||
public class ScheduleStatus {
|
||||
|
||||
private int activeMinutes;
|
||||
private boolean missedSchedules;
|
||||
|
||||
public ScheduleStatus(int activeMinutes, boolean missedSchedules) {
|
||||
this.activeMinutes = activeMinutes;
|
||||
this.missedSchedules = missedSchedules;
|
||||
}
|
||||
|
||||
public int getActiveMinutes() {
|
||||
return activeMinutes;
|
||||
}
|
||||
|
||||
public void setActiveMinutes(int activeMinutes) {
|
||||
this.activeMinutes = activeMinutes;
|
||||
}
|
||||
|
||||
public boolean isMissedSchedules() {
|
||||
return missedSchedules;
|
||||
}
|
||||
|
||||
public void setMissedSchedules(boolean missedSchedules) {
|
||||
this.missedSchedules = missedSchedules;
|
||||
}
|
||||
}
|
@ -0,0 +1,18 @@
|
||||
package core.api.models.timemanager.taskSchedule;
|
||||
|
||||
public class TaskScheduleStopResponse {
|
||||
|
||||
private int workTime;
|
||||
|
||||
public TaskScheduleStopResponse(int workTime) {
|
||||
this.workTime = workTime;
|
||||
}
|
||||
|
||||
public int getWorkTime() {
|
||||
return workTime;
|
||||
}
|
||||
|
||||
public void setWorkTime(int workTime) {
|
||||
this.workTime = workTime;
|
||||
}
|
||||
}
|
@ -0,0 +1,89 @@
|
||||
package core.api.models.timemanager.taskgroup;
|
||||
|
||||
import core.api.models.timemanager.tasks.TaskOverviewInfo;
|
||||
import core.entities.timemanager.Task;
|
||||
import core.entities.timemanager.Taskgroup;
|
||||
|
||||
import java.time.LocalDate;
|
||||
import java.util.ArrayList;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
||||
public class RecursiveTaskgroupInfo {
|
||||
|
||||
private long taskgroupID;
|
||||
private String taskgroupName;
|
||||
|
||||
private boolean hasOverdueTask;
|
||||
|
||||
private int amountActiveTasks;
|
||||
|
||||
private List<RecursiveTaskgroupInfo> childTaskgroups = new ArrayList<>();
|
||||
|
||||
private List<TaskOverviewInfo> activeTasks = new LinkedList<>();
|
||||
|
||||
public RecursiveTaskgroupInfo(Taskgroup taskgroup) {
|
||||
this.taskgroupID = taskgroup.getTaskgroupID();
|
||||
this.taskgroupName = taskgroup.getTaskgroupName();
|
||||
|
||||
for(Taskgroup child : taskgroup.getChildren()) {
|
||||
this.childTaskgroups.add(new RecursiveTaskgroupInfo(child));
|
||||
}
|
||||
|
||||
for(Task task : taskgroup.getActiveTasks()) {
|
||||
this.activeTasks.add(new TaskOverviewInfo(task));
|
||||
if(task.getDeadline().isBefore(LocalDate.now())) {
|
||||
this.hasOverdueTask = true;
|
||||
}
|
||||
}
|
||||
this.amountActiveTasks = taskgroup.getAmountOfActiveTasks();
|
||||
}
|
||||
|
||||
public long getTaskgroupID() {
|
||||
return taskgroupID;
|
||||
}
|
||||
|
||||
public void setTaskgroupID(long taskgroupID) {
|
||||
this.taskgroupID = taskgroupID;
|
||||
}
|
||||
|
||||
public String getTaskgroupName() {
|
||||
return taskgroupName;
|
||||
}
|
||||
|
||||
public void setTaskgroupName(String taskgroupName) {
|
||||
this.taskgroupName = taskgroupName;
|
||||
}
|
||||
|
||||
public List<RecursiveTaskgroupInfo> getChildTaskgroups() {
|
||||
return childTaskgroups;
|
||||
}
|
||||
|
||||
public void setChildTaskgroups(List<RecursiveTaskgroupInfo> childTaskgroups) {
|
||||
this.childTaskgroups = childTaskgroups;
|
||||
}
|
||||
|
||||
public List<TaskOverviewInfo> getActiveTasks() {
|
||||
return activeTasks;
|
||||
}
|
||||
|
||||
public void setActiveTasks(List<TaskOverviewInfo> activeTasks) {
|
||||
this.activeTasks = activeTasks;
|
||||
}
|
||||
|
||||
public boolean isHasOverdueTask() {
|
||||
return hasOverdueTask;
|
||||
}
|
||||
|
||||
public void setHasOverdueTask(boolean hasOverdueTask) {
|
||||
this.hasOverdueTask = hasOverdueTask;
|
||||
}
|
||||
|
||||
public int getAmountActiveTasks() {
|
||||
return amountActiveTasks;
|
||||
}
|
||||
|
||||
public void setAmountActiveTasks(int amountActiveTasks) {
|
||||
this.amountActiveTasks = amountActiveTasks;
|
||||
}
|
||||
}
|
@ -0,0 +1,72 @@
|
||||
package core.api.models.timemanager.tasks;
|
||||
|
||||
import core.entities.timemanager.Task;
|
||||
|
||||
import java.time.LocalDate;
|
||||
|
||||
public class TaskOverviewInfo {
|
||||
|
||||
private long taskID;
|
||||
private String taskName;
|
||||
private int activeMinutes;
|
||||
private int eta;
|
||||
private LocalDate limit;
|
||||
private boolean overdue;
|
||||
|
||||
public TaskOverviewInfo(Task task) {
|
||||
this.taskID = task.getTaskID();
|
||||
this.taskName = task.getTaskName();
|
||||
this.activeMinutes = task.getWorkTime();
|
||||
this.eta = task.getEta();
|
||||
this.limit = task.getDeadline();
|
||||
this.overdue = LocalDate.now().isAfter(task.getDeadline());
|
||||
}
|
||||
|
||||
public long getTaskID() {
|
||||
return taskID;
|
||||
}
|
||||
|
||||
public void setTaskID(long taskID) {
|
||||
this.taskID = taskID;
|
||||
}
|
||||
|
||||
public String getTaskName() {
|
||||
return taskName;
|
||||
}
|
||||
|
||||
public void setTaskName(String taskName) {
|
||||
this.taskName = taskName;
|
||||
}
|
||||
|
||||
public int getActiveMinutes() {
|
||||
return activeMinutes;
|
||||
}
|
||||
|
||||
public void setActiveMinutes(int activeMinutes) {
|
||||
this.activeMinutes = activeMinutes;
|
||||
}
|
||||
|
||||
public int getEta() {
|
||||
return eta;
|
||||
}
|
||||
|
||||
public void setEta(int eta) {
|
||||
this.eta = eta;
|
||||
}
|
||||
|
||||
public LocalDate getLimit() {
|
||||
return limit;
|
||||
}
|
||||
|
||||
public void setLimit(LocalDate limit) {
|
||||
this.limit = limit;
|
||||
}
|
||||
|
||||
public boolean isOverdue() {
|
||||
return overdue;
|
||||
}
|
||||
|
||||
public void setOverdue(boolean overdue) {
|
||||
this.overdue = overdue;
|
||||
}
|
||||
}
|
@ -3,6 +3,7 @@ package core.entities.timemanager;
|
||||
import javax.persistence.*;
|
||||
import java.time.LocalDate;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.Objects;
|
||||
|
||||
@Entity
|
||||
@Table(name = "basic_schedules")
|
||||
@ -75,4 +76,21 @@ public class BasicTaskSchedule {
|
||||
public void setFinishedTime(LocalDateTime finishedTime) {
|
||||
this.finishedTime = finishedTime;
|
||||
}
|
||||
|
||||
public boolean isActivateAble() {
|
||||
return startTime == null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
BasicTaskSchedule that = (BasicTaskSchedule) o;
|
||||
return scheduleID == that.scheduleID;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(scheduleID);
|
||||
}
|
||||
}
|
||||
|
@ -2,6 +2,8 @@ package core.entities.timemanager;
|
||||
|
||||
import javax.persistence.*;
|
||||
import java.time.LocalDate;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
|
||||
@ -27,7 +29,7 @@ public class Task {
|
||||
private boolean finished;
|
||||
|
||||
@OneToMany(mappedBy = "task", cascade = CascadeType.ALL, fetch = FetchType.EAGER)
|
||||
private Set<BasicTaskSchedule> basicTaskSchedules;
|
||||
private List<BasicTaskSchedule> basicTaskSchedules;
|
||||
|
||||
private int workTime;
|
||||
|
||||
@ -128,11 +130,11 @@ public class Task {
|
||||
this.taskID = taskID;
|
||||
}
|
||||
|
||||
public Set<BasicTaskSchedule> getBasicTaskSchedules() {
|
||||
public List<BasicTaskSchedule> getBasicTaskSchedules() {
|
||||
return basicTaskSchedules;
|
||||
}
|
||||
|
||||
public void setBasicTaskSchedules(Set<BasicTaskSchedule> basicTaskSchedules) {
|
||||
public void setBasicTaskSchedules(List<BasicTaskSchedule> basicTaskSchedules) {
|
||||
this.basicTaskSchedules = basicTaskSchedules;
|
||||
}
|
||||
|
||||
|
@ -97,4 +97,22 @@ public class Taskgroup {
|
||||
}
|
||||
return ancestors;
|
||||
}
|
||||
|
||||
public List<Task> getActiveTasks() {
|
||||
List<Task> tasks = new LinkedList<>();
|
||||
for(Task task : this.tasks) {
|
||||
if(!task.isFinished()) {
|
||||
tasks.add(task);
|
||||
}
|
||||
}
|
||||
return tasks;
|
||||
}
|
||||
|
||||
public int getAmountOfActiveTasks() {
|
||||
int activeAmountTasks = getActiveTasks().size();
|
||||
for(Taskgroup taskgroup : children) {
|
||||
activeAmountTasks += taskgroup.getAmountOfActiveTasks();
|
||||
}
|
||||
return activeAmountTasks;
|
||||
}
|
||||
}
|
||||
|
@ -11,6 +11,7 @@ import org.springframework.stereotype.Repository;
|
||||
import javax.transaction.Transactional;
|
||||
import java.time.LocalDate;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
@Repository
|
||||
public interface BasicTaskScheduleRepository extends CrudRepository<BasicTaskSchedule, Long> {
|
||||
@ -30,4 +31,9 @@ public interface BasicTaskScheduleRepository extends CrudRepository<BasicTaskSch
|
||||
|
||||
@Query(value = "SELECT bts FROM BasicTaskSchedule bts WHERE bts.task.taskgroup.user = ?1 AND bts.scheduleDate = ?2")
|
||||
List<BasicTaskSchedule> findAllByUserAndDate(User user, LocalDate localDate);
|
||||
|
||||
@Query(value = "SELECT bts FROM BasicTaskSchedule bts WHERE bts.task.taskgroup.user.username = ?1 AND bts.startTime is not null and bts.finishedTime is null")
|
||||
Optional<BasicTaskSchedule> findActiveTaskSchedule(String username);
|
||||
|
||||
List<BasicTaskSchedule> findAllByStartTimeIsNull();
|
||||
}
|
||||
|
@ -4,5 +4,6 @@ public enum ServiceExitCode {
|
||||
|
||||
OK,
|
||||
ENTITY_ALREADY_EXIST,
|
||||
MISSING_ENTITY;
|
||||
MISSING_ENTITY,
|
||||
INVALID_OPERATION;
|
||||
}
|
||||
|
@ -8,9 +8,13 @@ import core.repositories.UserRepository;
|
||||
import core.repositories.timemanager.BasicTaskScheduleRepository;
|
||||
import core.repositories.timemanager.TaskRepository;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.security.core.context.SecurityContextHolder;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.time.Duration;
|
||||
import java.time.LocalDate;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
@ -52,10 +56,22 @@ public class TaskScheduleService {
|
||||
basicTaskScheduleRepository.deleteBasicTaskScheduleByID(basicTaskSchedule.getScheduleID());
|
||||
}
|
||||
|
||||
public ServiceResult<List<BasicTaskSchedule>> loadTodaysSchedule(String username) {
|
||||
public ServiceResult<List<BasicTaskSchedule>> loadTodaysSchedule(String username, boolean onlyActivateable) {
|
||||
Optional<User> user = userRepository.findByUsername(username);
|
||||
return user.map(value -> new ServiceResult<>(basicTaskScheduleRepository.findAllByUserAndDate(value, LocalDate.now()))).orElseGet(() ->
|
||||
new ServiceResult<>(ServiceExitCode.MISSING_ENTITY));
|
||||
if(user.isEmpty()) {
|
||||
return new ServiceResult<>(ServiceExitCode.MISSING_ENTITY);
|
||||
}
|
||||
|
||||
List<BasicTaskSchedule> basicTaskSchedules = basicTaskScheduleRepository.findAllByUserAndDate(user.get(), LocalDate.now());
|
||||
List<BasicTaskSchedule> activatableSchedules = new LinkedList<>();
|
||||
if(onlyActivateable) {
|
||||
for (BasicTaskSchedule basicTaskSchedule : basicTaskSchedules) {
|
||||
if (basicTaskSchedule.isActivateAble()) {
|
||||
activatableSchedules.add(basicTaskSchedule);
|
||||
}
|
||||
}
|
||||
}
|
||||
return new ServiceResult<>(activatableSchedules);
|
||||
}
|
||||
|
||||
public ServiceResult<List<BasicTaskSchedule>> loadSchedules(String username) {
|
||||
@ -70,6 +86,7 @@ public class TaskScheduleService {
|
||||
return new ServiceResult<>(ServiceExitCode.ENTITY_ALREADY_EXIST);
|
||||
} else {
|
||||
BasicTaskSchedule basicTaskSchedule = new BasicTaskSchedule(task, LocalDate.now());
|
||||
basicTaskSchedule.setStartTime(LocalDateTime.now());
|
||||
task.getBasicTaskSchedules().add(basicTaskSchedule);
|
||||
basicTaskScheduleRepository.save(basicTaskSchedule);
|
||||
taskRepository.save(task);
|
||||
@ -80,4 +97,63 @@ public class TaskScheduleService {
|
||||
public void deleteScheduleByTask(Task task) {
|
||||
basicTaskScheduleRepository.deleteAllByTask(task);
|
||||
}
|
||||
|
||||
public ServiceResult<BasicTaskSchedule> getActiveSchedule(String username) {
|
||||
Optional<BasicTaskSchedule> activeTaskScheduleResult = basicTaskScheduleRepository.findActiveTaskSchedule(username);
|
||||
return activeTaskScheduleResult.map(ServiceResult::new).orElseGet(() -> new ServiceResult<>(ServiceExitCode.MISSING_ENTITY));
|
||||
}
|
||||
|
||||
public ServiceResult<BasicTaskSchedule> activateSchedule(BasicTaskSchedule taskSchedule) {
|
||||
//Check if taskSchedule can be started
|
||||
if(taskSchedule.getStartTime() != null) {
|
||||
return new ServiceResult<>(ServiceExitCode.INVALID_OPERATION);
|
||||
}
|
||||
|
||||
if(getActiveSchedule(taskSchedule.getTask().getTaskgroup().getUser().getUsername()).getExitCode() == ServiceExitCode.MISSING_ENTITY) {
|
||||
taskSchedule.setStartTime(LocalDateTime.now());
|
||||
basicTaskScheduleRepository.save(taskSchedule);
|
||||
return new ServiceResult<>(taskSchedule);
|
||||
} else {
|
||||
return new ServiceResult<>(ServiceExitCode.ENTITY_ALREADY_EXIST);
|
||||
}
|
||||
}
|
||||
|
||||
public ServiceResult<Integer> stopSchedule(BasicTaskSchedule taskSchedule, boolean finish) {
|
||||
if(taskSchedule.getStartTime() == null || taskSchedule.getFinishedTime() != null) {
|
||||
return new ServiceResult<>(ServiceExitCode.INVALID_OPERATION);
|
||||
}
|
||||
|
||||
taskSchedule.setFinishedTime(LocalDateTime.now());
|
||||
long activeTime = Duration.between(taskSchedule.getStartTime(), taskSchedule.getFinishedTime()).toMinutes();
|
||||
long workTime = taskSchedule.getTask().getWorkTime() + activeTime;
|
||||
taskSchedule.getTask().setWorkTime((int) workTime);
|
||||
if(finish) {
|
||||
taskSchedule.getTask().setFinished(true);
|
||||
}
|
||||
basicTaskScheduleRepository.save(taskSchedule);
|
||||
taskRepository.save(taskSchedule.getTask());
|
||||
return new ServiceResult<>((int) activeTime);
|
||||
}
|
||||
|
||||
public int getWorkedMinutes(User user) {
|
||||
List<BasicTaskSchedule> basicTaskSchedules = basicTaskScheduleRepository.findAllByUser(user);
|
||||
long workedMinutes = 0;
|
||||
for(BasicTaskSchedule basicTaskSchedule : basicTaskSchedules) {
|
||||
if(basicTaskSchedule.getFinishedTime() != null && basicTaskSchedule.getFinishedTime().toLocalDate().isEqual(LocalDate.now())) {
|
||||
workedMinutes += Duration.between(basicTaskSchedule.getStartTime(), basicTaskSchedule.getFinishedTime()).toMinutes();
|
||||
}
|
||||
}
|
||||
return (int) workedMinutes;
|
||||
}
|
||||
|
||||
public boolean isAnyScheduleMissed(User user) {
|
||||
List<BasicTaskSchedule> unstartedSchedules = basicTaskScheduleRepository.findAllByStartTimeIsNull();
|
||||
LocalDate dateReference = LocalDate.now();
|
||||
for(BasicTaskSchedule schedule : unstartedSchedules) {
|
||||
if(schedule.getScheduleDate().isBefore(dateReference)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,7 @@
|
||||
package core.services;
|
||||
|
||||
import core.api.models.timemanager.tasks.TaskFieldInfo;
|
||||
import core.entities.timemanager.BasicTaskSchedule;
|
||||
import core.entities.timemanager.Task;
|
||||
import core.entities.timemanager.Taskgroup;
|
||||
import core.repositories.timemanager.BasicTaskScheduleRepository;
|
||||
@ -9,8 +10,8 @@ import core.repositories.timemanager.TaskgroupRepository;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Optional;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.*;
|
||||
|
||||
@Service
|
||||
public class TaskService {
|
||||
@ -75,4 +76,26 @@ public class TaskService {
|
||||
public void clearTasks(Taskgroup taskgroup) {
|
||||
taskRepository.deleteAllByTaskgroup(taskgroup);
|
||||
}
|
||||
|
||||
public void finishTask(Task task) {
|
||||
//Mark task as finished and remove all unstarted schedules as well as finish all started schedules
|
||||
task.finish();
|
||||
taskRepository.save(task);
|
||||
|
||||
List<BasicTaskSchedule> removedBasicTaskSchedules = new LinkedList<>();
|
||||
for(BasicTaskSchedule basicTaskSchedule : task.getBasicTaskSchedules()) {
|
||||
if(basicTaskSchedule.getStartTime() == null) {
|
||||
removedBasicTaskSchedules.add(basicTaskSchedule);
|
||||
} else if(basicTaskSchedule.getFinishedTime() == null) {
|
||||
ServiceResult<?> result = taskScheduleService.stopSchedule(basicTaskSchedule, true);
|
||||
System.out.println(result);
|
||||
}
|
||||
}
|
||||
|
||||
for(BasicTaskSchedule deletedTaskSchedule: removedBasicTaskSchedules) {
|
||||
task.getBasicTaskSchedules().remove(deletedTaskSchedule);
|
||||
taskRepository.save(task);
|
||||
taskScheduleService.deleteBasicSchedule(deletedTaskSchedule);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -28,11 +28,16 @@ model/passwordChangeRequest.ts
|
||||
model/propertiesInfo.ts
|
||||
model/propertyInfo.ts
|
||||
model/propertyUpdateRequest.ts
|
||||
model/recursiveTaskgroupInfo.ts
|
||||
model/scheduleActivateInfo.ts
|
||||
model/scheduleInfo.ts
|
||||
model/scheduleStatus.ts
|
||||
model/signUpRequest.ts
|
||||
model/simpleStatusResponse.ts
|
||||
model/taskEntityInfo.ts
|
||||
model/taskFieldInfo.ts
|
||||
model/taskOverviewInfo.ts
|
||||
model/taskScheduleStopResponse.ts
|
||||
model/taskShortInfo.ts
|
||||
model/taskgroupDetailInfo.ts
|
||||
model/taskgroupEntityInfo.ts
|
||||
|
@ -20,8 +20,11 @@ import { Observable } from 'rxjs';
|
||||
|
||||
import { BasicScheduleEntityInfo } from '../model/models';
|
||||
import { BasicScheduleFieldInfo } from '../model/models';
|
||||
import { ScheduleActivateInfo } from '../model/models';
|
||||
import { ScheduleInfo } from '../model/models';
|
||||
import { ScheduleStatus } from '../model/models';
|
||||
import { SimpleStatusResponse } from '../model/models';
|
||||
import { TaskScheduleStopResponse } from '../model/models';
|
||||
|
||||
import { BASE_PATH, COLLECTION_FORMATS } from '../variables';
|
||||
import { Configuration } from '../configuration';
|
||||
@ -88,6 +91,61 @@ export class ScheduleService {
|
||||
return httpParams;
|
||||
}
|
||||
|
||||
/**
|
||||
* get active schedule
|
||||
* get active schedule
|
||||
* @param observe set whether or not to return the data Observable as the body, response or events. defaults to returning the body.
|
||||
* @param reportProgress flag to report request and response progress.
|
||||
*/
|
||||
public schedulesActiveGet(observe?: 'body', reportProgress?: boolean, options?: {httpHeaderAccept?: 'application/json', context?: HttpContext}): Observable<ScheduleInfo>;
|
||||
public schedulesActiveGet(observe?: 'response', reportProgress?: boolean, options?: {httpHeaderAccept?: 'application/json', context?: HttpContext}): Observable<HttpResponse<ScheduleInfo>>;
|
||||
public schedulesActiveGet(observe?: 'events', reportProgress?: boolean, options?: {httpHeaderAccept?: 'application/json', context?: HttpContext}): Observable<HttpEvent<ScheduleInfo>>;
|
||||
public schedulesActiveGet(observe: any = 'body', reportProgress: boolean = false, options?: {httpHeaderAccept?: 'application/json', context?: HttpContext}): Observable<any> {
|
||||
|
||||
let localVarHeaders = this.defaultHeaders;
|
||||
|
||||
let localVarCredential: string | undefined;
|
||||
// authentication (API_TOKEN) required
|
||||
localVarCredential = this.configuration.lookupCredential('API_TOKEN');
|
||||
if (localVarCredential) {
|
||||
localVarHeaders = localVarHeaders.set('Authorization', 'Bearer ' + localVarCredential);
|
||||
}
|
||||
|
||||
let localVarHttpHeaderAcceptSelected: string | undefined = options && options.httpHeaderAccept;
|
||||
if (localVarHttpHeaderAcceptSelected === undefined) {
|
||||
// to determine the Accept header
|
||||
const httpHeaderAccepts: string[] = [
|
||||
'application/json'
|
||||
];
|
||||
localVarHttpHeaderAcceptSelected = this.configuration.selectHeaderAccept(httpHeaderAccepts);
|
||||
}
|
||||
if (localVarHttpHeaderAcceptSelected !== undefined) {
|
||||
localVarHeaders = localVarHeaders.set('Accept', localVarHttpHeaderAcceptSelected);
|
||||
}
|
||||
|
||||
let localVarHttpContext: HttpContext | undefined = options && options.context;
|
||||
if (localVarHttpContext === undefined) {
|
||||
localVarHttpContext = new HttpContext();
|
||||
}
|
||||
|
||||
|
||||
let responseType_: 'text' | 'json' = 'json';
|
||||
if(localVarHttpHeaderAcceptSelected && localVarHttpHeaderAcceptSelected.startsWith('text')) {
|
||||
responseType_ = 'text';
|
||||
}
|
||||
|
||||
return this.httpClient.get<ScheduleInfo>(`${this.configuration.basePath}/schedules/active`,
|
||||
{
|
||||
context: localVarHttpContext,
|
||||
responseType: <any>responseType_,
|
||||
withCredentials: this.configuration.withCredentials,
|
||||
headers: localVarHeaders,
|
||||
observe: observe,
|
||||
reportProgress: reportProgress
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* gets all schedules of user
|
||||
* gets all schedules of user
|
||||
@ -143,6 +201,66 @@ export class ScheduleService {
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* activates schedule
|
||||
* activates schedule
|
||||
* @param scheduleID internal id of schedule
|
||||
* @param observe set whether or not to return the data Observable as the body, response or events. defaults to returning the body.
|
||||
* @param reportProgress flag to report request and response progress.
|
||||
*/
|
||||
public schedulesScheduleIDActivatePost(scheduleID: number, observe?: 'body', reportProgress?: boolean, options?: {httpHeaderAccept?: 'application/json', context?: HttpContext}): Observable<ScheduleActivateInfo>;
|
||||
public schedulesScheduleIDActivatePost(scheduleID: number, observe?: 'response', reportProgress?: boolean, options?: {httpHeaderAccept?: 'application/json', context?: HttpContext}): Observable<HttpResponse<ScheduleActivateInfo>>;
|
||||
public schedulesScheduleIDActivatePost(scheduleID: number, observe?: 'events', reportProgress?: boolean, options?: {httpHeaderAccept?: 'application/json', context?: HttpContext}): Observable<HttpEvent<ScheduleActivateInfo>>;
|
||||
public schedulesScheduleIDActivatePost(scheduleID: number, observe: any = 'body', reportProgress: boolean = false, options?: {httpHeaderAccept?: 'application/json', context?: HttpContext}): Observable<any> {
|
||||
if (scheduleID === null || scheduleID === undefined) {
|
||||
throw new Error('Required parameter scheduleID was null or undefined when calling schedulesScheduleIDActivatePost.');
|
||||
}
|
||||
|
||||
let localVarHeaders = this.defaultHeaders;
|
||||
|
||||
let localVarCredential: string | undefined;
|
||||
// authentication (API_TOKEN) required
|
||||
localVarCredential = this.configuration.lookupCredential('API_TOKEN');
|
||||
if (localVarCredential) {
|
||||
localVarHeaders = localVarHeaders.set('Authorization', 'Bearer ' + localVarCredential);
|
||||
}
|
||||
|
||||
let localVarHttpHeaderAcceptSelected: string | undefined = options && options.httpHeaderAccept;
|
||||
if (localVarHttpHeaderAcceptSelected === undefined) {
|
||||
// to determine the Accept header
|
||||
const httpHeaderAccepts: string[] = [
|
||||
'application/json'
|
||||
];
|
||||
localVarHttpHeaderAcceptSelected = this.configuration.selectHeaderAccept(httpHeaderAccepts);
|
||||
}
|
||||
if (localVarHttpHeaderAcceptSelected !== undefined) {
|
||||
localVarHeaders = localVarHeaders.set('Accept', localVarHttpHeaderAcceptSelected);
|
||||
}
|
||||
|
||||
let localVarHttpContext: HttpContext | undefined = options && options.context;
|
||||
if (localVarHttpContext === undefined) {
|
||||
localVarHttpContext = new HttpContext();
|
||||
}
|
||||
|
||||
|
||||
let responseType_: 'text' | 'json' = 'json';
|
||||
if(localVarHttpHeaderAcceptSelected && localVarHttpHeaderAcceptSelected.startsWith('text')) {
|
||||
responseType_ = 'text';
|
||||
}
|
||||
|
||||
return this.httpClient.post<ScheduleActivateInfo>(`${this.configuration.basePath}/schedules/${encodeURIComponent(String(scheduleID))}/activate`,
|
||||
null,
|
||||
{
|
||||
context: localVarHttpContext,
|
||||
responseType: <any>responseType_,
|
||||
withCredentials: this.configuration.withCredentials,
|
||||
headers: localVarHeaders,
|
||||
observe: observe,
|
||||
reportProgress: reportProgress
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* reschedules task
|
||||
* reschedules a task
|
||||
@ -276,6 +394,123 @@ export class ScheduleService {
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param scheduleID internal id of schedule
|
||||
* @param finish internal id of schedule
|
||||
* @param observe set whether or not to return the data Observable as the body, response or events. defaults to returning the body.
|
||||
* @param reportProgress flag to report request and response progress.
|
||||
*/
|
||||
public schedulesScheduleIDStopFinishPost(scheduleID: number, finish: boolean, observe?: 'body', reportProgress?: boolean, options?: {httpHeaderAccept?: 'application/json', context?: HttpContext}): Observable<TaskScheduleStopResponse>;
|
||||
public schedulesScheduleIDStopFinishPost(scheduleID: number, finish: boolean, observe?: 'response', reportProgress?: boolean, options?: {httpHeaderAccept?: 'application/json', context?: HttpContext}): Observable<HttpResponse<TaskScheduleStopResponse>>;
|
||||
public schedulesScheduleIDStopFinishPost(scheduleID: number, finish: boolean, observe?: 'events', reportProgress?: boolean, options?: {httpHeaderAccept?: 'application/json', context?: HttpContext}): Observable<HttpEvent<TaskScheduleStopResponse>>;
|
||||
public schedulesScheduleIDStopFinishPost(scheduleID: number, finish: boolean, observe: any = 'body', reportProgress: boolean = false, options?: {httpHeaderAccept?: 'application/json', context?: HttpContext}): Observable<any> {
|
||||
if (scheduleID === null || scheduleID === undefined) {
|
||||
throw new Error('Required parameter scheduleID was null or undefined when calling schedulesScheduleIDStopFinishPost.');
|
||||
}
|
||||
if (finish === null || finish === undefined) {
|
||||
throw new Error('Required parameter finish was null or undefined when calling schedulesScheduleIDStopFinishPost.');
|
||||
}
|
||||
|
||||
let localVarHeaders = this.defaultHeaders;
|
||||
|
||||
let localVarCredential: string | undefined;
|
||||
// authentication (API_TOKEN) required
|
||||
localVarCredential = this.configuration.lookupCredential('API_TOKEN');
|
||||
if (localVarCredential) {
|
||||
localVarHeaders = localVarHeaders.set('Authorization', 'Bearer ' + localVarCredential);
|
||||
}
|
||||
|
||||
let localVarHttpHeaderAcceptSelected: string | undefined = options && options.httpHeaderAccept;
|
||||
if (localVarHttpHeaderAcceptSelected === undefined) {
|
||||
// to determine the Accept header
|
||||
const httpHeaderAccepts: string[] = [
|
||||
'application/json'
|
||||
];
|
||||
localVarHttpHeaderAcceptSelected = this.configuration.selectHeaderAccept(httpHeaderAccepts);
|
||||
}
|
||||
if (localVarHttpHeaderAcceptSelected !== undefined) {
|
||||
localVarHeaders = localVarHeaders.set('Accept', localVarHttpHeaderAcceptSelected);
|
||||
}
|
||||
|
||||
let localVarHttpContext: HttpContext | undefined = options && options.context;
|
||||
if (localVarHttpContext === undefined) {
|
||||
localVarHttpContext = new HttpContext();
|
||||
}
|
||||
|
||||
|
||||
let responseType_: 'text' | 'json' = 'json';
|
||||
if(localVarHttpHeaderAcceptSelected && localVarHttpHeaderAcceptSelected.startsWith('text')) {
|
||||
responseType_ = 'text';
|
||||
}
|
||||
|
||||
return this.httpClient.post<TaskScheduleStopResponse>(`${this.configuration.basePath}/schedules/${encodeURIComponent(String(scheduleID))}/stop/${encodeURIComponent(String(finish))}`,
|
||||
null,
|
||||
{
|
||||
context: localVarHttpContext,
|
||||
responseType: <any>responseType_,
|
||||
withCredentials: this.configuration.withCredentials,
|
||||
headers: localVarHeaders,
|
||||
observe: observe,
|
||||
reportProgress: reportProgress
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* get number of active minutes
|
||||
* get number of worked minutes today
|
||||
* @param observe set whether or not to return the data Observable as the body, response or events. defaults to returning the body.
|
||||
* @param reportProgress flag to report request and response progress.
|
||||
*/
|
||||
public schedulesStatusTodayGet(observe?: 'body', reportProgress?: boolean, options?: {httpHeaderAccept?: 'application/json', context?: HttpContext}): Observable<ScheduleStatus>;
|
||||
public schedulesStatusTodayGet(observe?: 'response', reportProgress?: boolean, options?: {httpHeaderAccept?: 'application/json', context?: HttpContext}): Observable<HttpResponse<ScheduleStatus>>;
|
||||
public schedulesStatusTodayGet(observe?: 'events', reportProgress?: boolean, options?: {httpHeaderAccept?: 'application/json', context?: HttpContext}): Observable<HttpEvent<ScheduleStatus>>;
|
||||
public schedulesStatusTodayGet(observe: any = 'body', reportProgress: boolean = false, options?: {httpHeaderAccept?: 'application/json', context?: HttpContext}): Observable<any> {
|
||||
|
||||
let localVarHeaders = this.defaultHeaders;
|
||||
|
||||
let localVarCredential: string | undefined;
|
||||
// authentication (API_TOKEN) required
|
||||
localVarCredential = this.configuration.lookupCredential('API_TOKEN');
|
||||
if (localVarCredential) {
|
||||
localVarHeaders = localVarHeaders.set('Authorization', 'Bearer ' + localVarCredential);
|
||||
}
|
||||
|
||||
let localVarHttpHeaderAcceptSelected: string | undefined = options && options.httpHeaderAccept;
|
||||
if (localVarHttpHeaderAcceptSelected === undefined) {
|
||||
// to determine the Accept header
|
||||
const httpHeaderAccepts: string[] = [
|
||||
'application/json'
|
||||
];
|
||||
localVarHttpHeaderAcceptSelected = this.configuration.selectHeaderAccept(httpHeaderAccepts);
|
||||
}
|
||||
if (localVarHttpHeaderAcceptSelected !== undefined) {
|
||||
localVarHeaders = localVarHeaders.set('Accept', localVarHttpHeaderAcceptSelected);
|
||||
}
|
||||
|
||||
let localVarHttpContext: HttpContext | undefined = options && options.context;
|
||||
if (localVarHttpContext === undefined) {
|
||||
localVarHttpContext = new HttpContext();
|
||||
}
|
||||
|
||||
|
||||
let responseType_: 'text' | 'json' = 'json';
|
||||
if(localVarHttpHeaderAcceptSelected && localVarHttpHeaderAcceptSelected.startsWith('text')) {
|
||||
responseType_ = 'text';
|
||||
}
|
||||
|
||||
return this.httpClient.get<ScheduleStatus>(`${this.configuration.basePath}/schedules/status/today`,
|
||||
{
|
||||
context: localVarHttpContext,
|
||||
responseType: <any>responseType_,
|
||||
withCredentials: this.configuration.withCredentials,
|
||||
headers: localVarHeaders,
|
||||
observe: observe,
|
||||
reportProgress: reportProgress
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* creates basic schedule for task
|
||||
* creates a basic schedule for a task
|
||||
@ -353,9 +588,9 @@ export class ScheduleService {
|
||||
* @param observe set whether or not to return the data Observable as the body, response or events. defaults to returning the body.
|
||||
* @param reportProgress flag to report request and response progress.
|
||||
*/
|
||||
public schedulesTaskIDNowPost(taskID: number, observe?: 'body', reportProgress?: boolean, options?: {httpHeaderAccept?: 'application/json', context?: HttpContext}): Observable<BasicScheduleEntityInfo>;
|
||||
public schedulesTaskIDNowPost(taskID: number, observe?: 'response', reportProgress?: boolean, options?: {httpHeaderAccept?: 'application/json', context?: HttpContext}): Observable<HttpResponse<BasicScheduleEntityInfo>>;
|
||||
public schedulesTaskIDNowPost(taskID: number, observe?: 'events', reportProgress?: boolean, options?: {httpHeaderAccept?: 'application/json', context?: HttpContext}): Observable<HttpEvent<BasicScheduleEntityInfo>>;
|
||||
public schedulesTaskIDNowPost(taskID: number, observe?: 'body', reportProgress?: boolean, options?: {httpHeaderAccept?: 'application/json', context?: HttpContext}): Observable<ScheduleInfo>;
|
||||
public schedulesTaskIDNowPost(taskID: number, observe?: 'response', reportProgress?: boolean, options?: {httpHeaderAccept?: 'application/json', context?: HttpContext}): Observable<HttpResponse<ScheduleInfo>>;
|
||||
public schedulesTaskIDNowPost(taskID: number, observe?: 'events', reportProgress?: boolean, options?: {httpHeaderAccept?: 'application/json', context?: HttpContext}): Observable<HttpEvent<ScheduleInfo>>;
|
||||
public schedulesTaskIDNowPost(taskID: number, observe: any = 'body', reportProgress: boolean = false, options?: {httpHeaderAccept?: 'application/json', context?: HttpContext}): Observable<any> {
|
||||
if (taskID === null || taskID === undefined) {
|
||||
throw new Error('Required parameter taskID was null or undefined when calling schedulesTaskIDNowPost.');
|
||||
@ -393,7 +628,7 @@ export class ScheduleService {
|
||||
responseType_ = 'text';
|
||||
}
|
||||
|
||||
return this.httpClient.post<BasicScheduleEntityInfo>(`${this.configuration.basePath}/schedules/${encodeURIComponent(String(taskID))}/now`,
|
||||
return this.httpClient.post<ScheduleInfo>(`${this.configuration.basePath}/schedules/${encodeURIComponent(String(taskID))}/now`,
|
||||
null,
|
||||
{
|
||||
context: localVarHttpContext,
|
||||
@ -472,13 +707,17 @@ export class ScheduleService {
|
||||
/**
|
||||
* get today\'s schedules
|
||||
* get all schedules of today
|
||||
* @param activateable determines whether only schedules that can be started should be included or all schedules of today
|
||||
* @param observe set whether or not to return the data Observable as the body, response or events. defaults to returning the body.
|
||||
* @param reportProgress flag to report request and response progress.
|
||||
*/
|
||||
public schedulesTodayGet(observe?: 'body', reportProgress?: boolean, options?: {httpHeaderAccept?: 'application/json', context?: HttpContext}): Observable<Array<ScheduleInfo>>;
|
||||
public schedulesTodayGet(observe?: 'response', reportProgress?: boolean, options?: {httpHeaderAccept?: 'application/json', context?: HttpContext}): Observable<HttpResponse<Array<ScheduleInfo>>>;
|
||||
public schedulesTodayGet(observe?: 'events', reportProgress?: boolean, options?: {httpHeaderAccept?: 'application/json', context?: HttpContext}): Observable<HttpEvent<Array<ScheduleInfo>>>;
|
||||
public schedulesTodayGet(observe: any = 'body', reportProgress: boolean = false, options?: {httpHeaderAccept?: 'application/json', context?: HttpContext}): Observable<any> {
|
||||
public schedulesTodayActivateableGet(activateable: boolean, observe?: 'body', reportProgress?: boolean, options?: {httpHeaderAccept?: 'application/json', context?: HttpContext}): Observable<Array<ScheduleInfo>>;
|
||||
public schedulesTodayActivateableGet(activateable: boolean, observe?: 'response', reportProgress?: boolean, options?: {httpHeaderAccept?: 'application/json', context?: HttpContext}): Observable<HttpResponse<Array<ScheduleInfo>>>;
|
||||
public schedulesTodayActivateableGet(activateable: boolean, observe?: 'events', reportProgress?: boolean, options?: {httpHeaderAccept?: 'application/json', context?: HttpContext}): Observable<HttpEvent<Array<ScheduleInfo>>>;
|
||||
public schedulesTodayActivateableGet(activateable: boolean, observe: any = 'body', reportProgress: boolean = false, options?: {httpHeaderAccept?: 'application/json', context?: HttpContext}): Observable<any> {
|
||||
if (activateable === null || activateable === undefined) {
|
||||
throw new Error('Required parameter activateable was null or undefined when calling schedulesTodayActivateableGet.');
|
||||
}
|
||||
|
||||
let localVarHeaders = this.defaultHeaders;
|
||||
|
||||
@ -512,7 +751,7 @@ export class ScheduleService {
|
||||
responseType_ = 'text';
|
||||
}
|
||||
|
||||
return this.httpClient.get<Array<ScheduleInfo>>(`${this.configuration.basePath}/schedules/today`,
|
||||
return this.httpClient.get<Array<ScheduleInfo>>(`${this.configuration.basePath}/schedules/today/${encodeURIComponent(String(activateable))}`,
|
||||
{
|
||||
context: localVarHttpContext,
|
||||
responseType: <any>responseType_,
|
||||
|
144
frontend/src/api/api/schedules.service.ts
Normal file
144
frontend/src/api/api/schedules.service.ts
Normal file
@ -0,0 +1,144 @@
|
||||
/**
|
||||
* API Title
|
||||
* No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator)
|
||||
*
|
||||
* The version of the OpenAPI document: 1.0
|
||||
*
|
||||
*
|
||||
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
|
||||
* https://openapi-generator.tech
|
||||
* Do not edit the class manually.
|
||||
*/
|
||||
/* tslint:disable:no-unused-variable member-ordering */
|
||||
|
||||
import { Inject, Injectable, Optional } from '@angular/core';
|
||||
import { HttpClient, HttpHeaders, HttpParams,
|
||||
HttpResponse, HttpEvent, HttpParameterCodec, HttpContext
|
||||
} from '@angular/common/http';
|
||||
import { CustomHttpParameterCodec } from '../encoder';
|
||||
import { Observable } from 'rxjs';
|
||||
|
||||
import { ActiveMinutesInformation } from '../model/models';
|
||||
import { SimpleStatusResponse } from '../model/models';
|
||||
|
||||
import { BASE_PATH, COLLECTION_FORMATS } from '../variables';
|
||||
import { Configuration } from '../configuration';
|
||||
|
||||
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root'
|
||||
})
|
||||
export class SchedulesService {
|
||||
|
||||
protected basePath = 'http://localhost:8080/api';
|
||||
public defaultHeaders = new HttpHeaders();
|
||||
public configuration = new Configuration();
|
||||
public encoder: HttpParameterCodec;
|
||||
|
||||
constructor(protected httpClient: HttpClient, @Optional()@Inject(BASE_PATH) basePath: string, @Optional() configuration: Configuration) {
|
||||
if (configuration) {
|
||||
this.configuration = configuration;
|
||||
}
|
||||
if (typeof this.configuration.basePath !== 'string') {
|
||||
if (typeof basePath !== 'string') {
|
||||
basePath = this.basePath;
|
||||
}
|
||||
this.configuration.basePath = basePath;
|
||||
}
|
||||
this.encoder = this.configuration.encoder || new CustomHttpParameterCodec();
|
||||
}
|
||||
|
||||
|
||||
private addToHttpParams(httpParams: HttpParams, value: any, key?: string): HttpParams {
|
||||
if (typeof value === "object" && value instanceof Date === false) {
|
||||
httpParams = this.addToHttpParamsRecursive(httpParams, value);
|
||||
} else {
|
||||
httpParams = this.addToHttpParamsRecursive(httpParams, value, key);
|
||||
}
|
||||
return httpParams;
|
||||
}
|
||||
|
||||
private addToHttpParamsRecursive(httpParams: HttpParams, value?: any, key?: string): HttpParams {
|
||||
if (value == null) {
|
||||
return httpParams;
|
||||
}
|
||||
|
||||
if (typeof value === "object") {
|
||||
if (Array.isArray(value)) {
|
||||
(value as any[]).forEach( elem => httpParams = this.addToHttpParamsRecursive(httpParams, elem, key));
|
||||
} else if (value instanceof Date) {
|
||||
if (key != null) {
|
||||
httpParams = httpParams.append(key,
|
||||
(value as Date).toISOString().substr(0, 10));
|
||||
} else {
|
||||
throw Error("key may not be null if value is Date");
|
||||
}
|
||||
} else {
|
||||
Object.keys(value).forEach( k => httpParams = this.addToHttpParamsRecursive(
|
||||
httpParams, value[k], key != null ? `${key}.${k}` : k));
|
||||
}
|
||||
} else if (key != null) {
|
||||
httpParams = httpParams.append(key, value);
|
||||
} else {
|
||||
throw Error("key may not be null if value is not object or array");
|
||||
}
|
||||
return httpParams;
|
||||
}
|
||||
|
||||
/**
|
||||
* get number of active minutes
|
||||
* get number of worked minutes today
|
||||
* @param observe set whether or not to return the data Observable as the body, response or events. defaults to returning the body.
|
||||
* @param reportProgress flag to report request and response progress.
|
||||
*/
|
||||
public schedulesWorkedMinutesTodayGet(observe?: 'body', reportProgress?: boolean, options?: {httpHeaderAccept?: 'application/json', context?: HttpContext}): Observable<ActiveMinutesInformation>;
|
||||
public schedulesWorkedMinutesTodayGet(observe?: 'response', reportProgress?: boolean, options?: {httpHeaderAccept?: 'application/json', context?: HttpContext}): Observable<HttpResponse<ActiveMinutesInformation>>;
|
||||
public schedulesWorkedMinutesTodayGet(observe?: 'events', reportProgress?: boolean, options?: {httpHeaderAccept?: 'application/json', context?: HttpContext}): Observable<HttpEvent<ActiveMinutesInformation>>;
|
||||
public schedulesWorkedMinutesTodayGet(observe: any = 'body', reportProgress: boolean = false, options?: {httpHeaderAccept?: 'application/json', context?: HttpContext}): Observable<any> {
|
||||
|
||||
let localVarHeaders = this.defaultHeaders;
|
||||
|
||||
let localVarCredential: string | undefined;
|
||||
// authentication (API_TOKEN) required
|
||||
localVarCredential = this.configuration.lookupCredential('API_TOKEN');
|
||||
if (localVarCredential) {
|
||||
localVarHeaders = localVarHeaders.set('Authorization', 'Bearer ' + localVarCredential);
|
||||
}
|
||||
|
||||
let localVarHttpHeaderAcceptSelected: string | undefined = options && options.httpHeaderAccept;
|
||||
if (localVarHttpHeaderAcceptSelected === undefined) {
|
||||
// to determine the Accept header
|
||||
const httpHeaderAccepts: string[] = [
|
||||
'application/json'
|
||||
];
|
||||
localVarHttpHeaderAcceptSelected = this.configuration.selectHeaderAccept(httpHeaderAccepts);
|
||||
}
|
||||
if (localVarHttpHeaderAcceptSelected !== undefined) {
|
||||
localVarHeaders = localVarHeaders.set('Accept', localVarHttpHeaderAcceptSelected);
|
||||
}
|
||||
|
||||
let localVarHttpContext: HttpContext | undefined = options && options.context;
|
||||
if (localVarHttpContext === undefined) {
|
||||
localVarHttpContext = new HttpContext();
|
||||
}
|
||||
|
||||
|
||||
let responseType_: 'text' | 'json' = 'json';
|
||||
if(localVarHttpHeaderAcceptSelected && localVarHttpHeaderAcceptSelected.startsWith('text')) {
|
||||
responseType_ = 'text';
|
||||
}
|
||||
|
||||
return this.httpClient.get<ActiveMinutesInformation>(`${this.configuration.basePath}/schedules/workedMinutesToday`,
|
||||
{
|
||||
context: localVarHttpContext,
|
||||
responseType: <any>responseType_,
|
||||
withCredentials: this.configuration.withCredentials,
|
||||
headers: localVarHeaders,
|
||||
observe: observe,
|
||||
reportProgress: reportProgress
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
}
|
@ -147,6 +147,66 @@ export class TaskService {
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* finishs task
|
||||
* finish tasks
|
||||
* @param taskID internal id of task
|
||||
* @param observe set whether or not to return the data Observable as the body, response or events. defaults to returning the body.
|
||||
* @param reportProgress flag to report request and response progress.
|
||||
*/
|
||||
public tasksTaskIDFinishPost(taskID: number, observe?: 'body', reportProgress?: boolean, options?: {httpHeaderAccept?: 'application/json', context?: HttpContext}): Observable<SimpleStatusResponse>;
|
||||
public tasksTaskIDFinishPost(taskID: number, observe?: 'response', reportProgress?: boolean, options?: {httpHeaderAccept?: 'application/json', context?: HttpContext}): Observable<HttpResponse<SimpleStatusResponse>>;
|
||||
public tasksTaskIDFinishPost(taskID: number, observe?: 'events', reportProgress?: boolean, options?: {httpHeaderAccept?: 'application/json', context?: HttpContext}): Observable<HttpEvent<SimpleStatusResponse>>;
|
||||
public tasksTaskIDFinishPost(taskID: number, observe: any = 'body', reportProgress: boolean = false, options?: {httpHeaderAccept?: 'application/json', context?: HttpContext}): Observable<any> {
|
||||
if (taskID === null || taskID === undefined) {
|
||||
throw new Error('Required parameter taskID was null or undefined when calling tasksTaskIDFinishPost.');
|
||||
}
|
||||
|
||||
let localVarHeaders = this.defaultHeaders;
|
||||
|
||||
let localVarCredential: string | undefined;
|
||||
// authentication (API_TOKEN) required
|
||||
localVarCredential = this.configuration.lookupCredential('API_TOKEN');
|
||||
if (localVarCredential) {
|
||||
localVarHeaders = localVarHeaders.set('Authorization', 'Bearer ' + localVarCredential);
|
||||
}
|
||||
|
||||
let localVarHttpHeaderAcceptSelected: string | undefined = options && options.httpHeaderAccept;
|
||||
if (localVarHttpHeaderAcceptSelected === undefined) {
|
||||
// to determine the Accept header
|
||||
const httpHeaderAccepts: string[] = [
|
||||
'application/json'
|
||||
];
|
||||
localVarHttpHeaderAcceptSelected = this.configuration.selectHeaderAccept(httpHeaderAccepts);
|
||||
}
|
||||
if (localVarHttpHeaderAcceptSelected !== undefined) {
|
||||
localVarHeaders = localVarHeaders.set('Accept', localVarHttpHeaderAcceptSelected);
|
||||
}
|
||||
|
||||
let localVarHttpContext: HttpContext | undefined = options && options.context;
|
||||
if (localVarHttpContext === undefined) {
|
||||
localVarHttpContext = new HttpContext();
|
||||
}
|
||||
|
||||
|
||||
let responseType_: 'text' | 'json' = 'json';
|
||||
if(localVarHttpHeaderAcceptSelected && localVarHttpHeaderAcceptSelected.startsWith('text')) {
|
||||
responseType_ = 'text';
|
||||
}
|
||||
|
||||
return this.httpClient.post<SimpleStatusResponse>(`${this.configuration.basePath}/tasks/${encodeURIComponent(String(taskID))}/finish`,
|
||||
null,
|
||||
{
|
||||
context: localVarHttpContext,
|
||||
responseType: <any>responseType_,
|
||||
withCredentials: this.configuration.withCredentials,
|
||||
headers: localVarHeaders,
|
||||
observe: observe,
|
||||
reportProgress: reportProgress
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* gets taskdetails
|
||||
* loads information about a given task
|
||||
|
@ -20,6 +20,7 @@ import { Observable } from 'rxjs';
|
||||
|
||||
import { InlineResponse200 } from '../model/models';
|
||||
import { InlineResponse403 } from '../model/models';
|
||||
import { RecursiveTaskgroupInfo } from '../model/models';
|
||||
import { SimpleStatusResponse } from '../model/models';
|
||||
import { TaskgroupDetailInfo } from '../model/models';
|
||||
import { TaskgroupEntityInfo } from '../model/models';
|
||||
@ -513,4 +514,59 @@ export class TaskgroupService {
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* list all top level taskgroups of authorized user
|
||||
* list all taskgroups of authorized user
|
||||
* @param observe set whether or not to return the data Observable as the body, response or events. defaults to returning the body.
|
||||
* @param reportProgress flag to report request and response progress.
|
||||
*/
|
||||
public taskgroupsTreeGet(observe?: 'body', reportProgress?: boolean, options?: {httpHeaderAccept?: 'application/json', context?: HttpContext}): Observable<Array<RecursiveTaskgroupInfo>>;
|
||||
public taskgroupsTreeGet(observe?: 'response', reportProgress?: boolean, options?: {httpHeaderAccept?: 'application/json', context?: HttpContext}): Observable<HttpResponse<Array<RecursiveTaskgroupInfo>>>;
|
||||
public taskgroupsTreeGet(observe?: 'events', reportProgress?: boolean, options?: {httpHeaderAccept?: 'application/json', context?: HttpContext}): Observable<HttpEvent<Array<RecursiveTaskgroupInfo>>>;
|
||||
public taskgroupsTreeGet(observe: any = 'body', reportProgress: boolean = false, options?: {httpHeaderAccept?: 'application/json', context?: HttpContext}): Observable<any> {
|
||||
|
||||
let localVarHeaders = this.defaultHeaders;
|
||||
|
||||
let localVarCredential: string | undefined;
|
||||
// authentication (API_TOKEN) required
|
||||
localVarCredential = this.configuration.lookupCredential('API_TOKEN');
|
||||
if (localVarCredential) {
|
||||
localVarHeaders = localVarHeaders.set('Authorization', 'Bearer ' + localVarCredential);
|
||||
}
|
||||
|
||||
let localVarHttpHeaderAcceptSelected: string | undefined = options && options.httpHeaderAccept;
|
||||
if (localVarHttpHeaderAcceptSelected === undefined) {
|
||||
// to determine the Accept header
|
||||
const httpHeaderAccepts: string[] = [
|
||||
'application/json'
|
||||
];
|
||||
localVarHttpHeaderAcceptSelected = this.configuration.selectHeaderAccept(httpHeaderAccepts);
|
||||
}
|
||||
if (localVarHttpHeaderAcceptSelected !== undefined) {
|
||||
localVarHeaders = localVarHeaders.set('Accept', localVarHttpHeaderAcceptSelected);
|
||||
}
|
||||
|
||||
let localVarHttpContext: HttpContext | undefined = options && options.context;
|
||||
if (localVarHttpContext === undefined) {
|
||||
localVarHttpContext = new HttpContext();
|
||||
}
|
||||
|
||||
|
||||
let responseType_: 'text' | 'json' = 'json';
|
||||
if(localVarHttpHeaderAcceptSelected && localVarHttpHeaderAcceptSelected.startsWith('text')) {
|
||||
responseType_ = 'text';
|
||||
}
|
||||
|
||||
return this.httpClient.get<Array<RecursiveTaskgroupInfo>>(`${this.configuration.basePath}/taskgroups/tree`,
|
||||
{
|
||||
context: localVarHttpContext,
|
||||
responseType: <any>responseType_,
|
||||
withCredentials: this.configuration.withCredentials,
|
||||
headers: localVarHeaders,
|
||||
observe: observe,
|
||||
reportProgress: reportProgress
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
|
20
frontend/src/api/model/activeMinutesInformation.ts
Normal file
20
frontend/src/api/model/activeMinutesInformation.ts
Normal file
@ -0,0 +1,20 @@
|
||||
/**
|
||||
* API Title
|
||||
* No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator)
|
||||
*
|
||||
* The version of the OpenAPI document: 1.0
|
||||
*
|
||||
*
|
||||
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
|
||||
* https://openapi-generator.tech
|
||||
* Do not edit the class manually.
|
||||
*/
|
||||
|
||||
|
||||
export interface ActiveMinutesInformation {
|
||||
/**
|
||||
* number of minutes it was worked today
|
||||
*/
|
||||
activeMinutes: number;
|
||||
}
|
||||
|
@ -12,11 +12,16 @@ export * from './passwordChangeRequest';
|
||||
export * from './propertiesInfo';
|
||||
export * from './propertyInfo';
|
||||
export * from './propertyUpdateRequest';
|
||||
export * from './recursiveTaskgroupInfo';
|
||||
export * from './scheduleActivateInfo';
|
||||
export * from './scheduleInfo';
|
||||
export * from './scheduleStatus';
|
||||
export * from './signUpRequest';
|
||||
export * from './simpleStatusResponse';
|
||||
export * from './taskEntityInfo';
|
||||
export * from './taskFieldInfo';
|
||||
export * from './taskOverviewInfo';
|
||||
export * from './taskScheduleStopResponse';
|
||||
export * from './taskShortInfo';
|
||||
export * from './taskgroupDetailInfo';
|
||||
export * from './taskgroupEntityInfo';
|
||||
|
35
frontend/src/api/model/recursiveTaskgroupInfo.ts
Normal file
35
frontend/src/api/model/recursiveTaskgroupInfo.ts
Normal file
@ -0,0 +1,35 @@
|
||||
/**
|
||||
* API Title
|
||||
* No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator)
|
||||
*
|
||||
* The version of the OpenAPI document: 1.0
|
||||
*
|
||||
*
|
||||
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
|
||||
* https://openapi-generator.tech
|
||||
* Do not edit the class manually.
|
||||
*/
|
||||
import { TaskOverviewInfo } from './taskOverviewInfo';
|
||||
|
||||
|
||||
export interface RecursiveTaskgroupInfo {
|
||||
/**
|
||||
* internal id of taskgroup
|
||||
*/
|
||||
taskgroupID: number;
|
||||
/**
|
||||
* name of taskgroup
|
||||
*/
|
||||
taskgroupName: string;
|
||||
childTaskgroups: Array<RecursiveTaskgroupInfo>;
|
||||
activeTasks: Array<TaskOverviewInfo>;
|
||||
/**
|
||||
* determines whether the taskgroup has an overdue task or not
|
||||
*/
|
||||
hasOverdueTask: boolean;
|
||||
/**
|
||||
* determines the number of active tasks that can be scheduled
|
||||
*/
|
||||
amountActiveTasks: number;
|
||||
}
|
||||
|
20
frontend/src/api/model/scheduleActivateInfo.ts
Normal file
20
frontend/src/api/model/scheduleActivateInfo.ts
Normal file
@ -0,0 +1,20 @@
|
||||
/**
|
||||
* API Title
|
||||
* No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator)
|
||||
*
|
||||
* The version of the OpenAPI document: 1.0
|
||||
*
|
||||
*
|
||||
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
|
||||
* https://openapi-generator.tech
|
||||
* Do not edit the class manually.
|
||||
*/
|
||||
|
||||
|
||||
export interface ScheduleActivateInfo {
|
||||
/**
|
||||
* point in time at which the schedule was started
|
||||
*/
|
||||
startTime: string;
|
||||
}
|
||||
|
24
frontend/src/api/model/scheduleStatus.ts
Normal file
24
frontend/src/api/model/scheduleStatus.ts
Normal file
@ -0,0 +1,24 @@
|
||||
/**
|
||||
* API Title
|
||||
* No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator)
|
||||
*
|
||||
* The version of the OpenAPI document: 1.0
|
||||
*
|
||||
*
|
||||
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
|
||||
* https://openapi-generator.tech
|
||||
* Do not edit the class manually.
|
||||
*/
|
||||
|
||||
|
||||
export interface ScheduleStatus {
|
||||
/**
|
||||
* number of minutes it was worked today
|
||||
*/
|
||||
activeMinutes: number;
|
||||
/**
|
||||
* states whether a schedule was missed or not
|
||||
*/
|
||||
missedSchedules: boolean;
|
||||
}
|
||||
|
40
frontend/src/api/model/taskOverviewInfo.ts
Normal file
40
frontend/src/api/model/taskOverviewInfo.ts
Normal file
@ -0,0 +1,40 @@
|
||||
/**
|
||||
* API Title
|
||||
* No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator)
|
||||
*
|
||||
* The version of the OpenAPI document: 1.0
|
||||
*
|
||||
*
|
||||
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
|
||||
* https://openapi-generator.tech
|
||||
* Do not edit the class manually.
|
||||
*/
|
||||
|
||||
|
||||
export interface TaskOverviewInfo {
|
||||
/**
|
||||
* internal id of task
|
||||
*/
|
||||
taskID: number;
|
||||
/**
|
||||
* name of task
|
||||
*/
|
||||
taskName: string;
|
||||
/**
|
||||
* expected time to finish task
|
||||
*/
|
||||
eta: number;
|
||||
/**
|
||||
* date until the task has to be finished
|
||||
*/
|
||||
limit: string;
|
||||
/**
|
||||
* determines whether the task is overdue
|
||||
*/
|
||||
overdue: boolean;
|
||||
/**
|
||||
* number in minutes that was already worked on this task
|
||||
*/
|
||||
activeTime?: number;
|
||||
}
|
||||
|
20
frontend/src/api/model/taskScheduleStopResponse.ts
Normal file
20
frontend/src/api/model/taskScheduleStopResponse.ts
Normal file
@ -0,0 +1,20 @@
|
||||
/**
|
||||
* API Title
|
||||
* No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator)
|
||||
*
|
||||
* The version of the OpenAPI document: 1.0
|
||||
*
|
||||
*
|
||||
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
|
||||
* https://openapi-generator.tech
|
||||
* Do not edit the class manually.
|
||||
*/
|
||||
|
||||
|
||||
export interface TaskScheduleStopResponse {
|
||||
/**
|
||||
* time where the schedule was active
|
||||
*/
|
||||
workTime: number;
|
||||
}
|
||||
|
@ -62,6 +62,11 @@ import { adapterFactory } from 'angular-calendar/date-adapters/date-fns';
|
||||
import {MatSelectModule} from "@angular/material/select";
|
||||
import { BasicSchedulerComponent } from './schedules/basic-scheduler/basic-scheduler.component';
|
||||
import { ScheduleDashboardComponent } from './schedules/schedule-dashboard/schedule-dashboard.component';
|
||||
import { DashboardComponent } from './dashboard/dashboard.component';
|
||||
import { ActiveScheduleComponent } from './dashboard/active-schedule/active-schedule.component';
|
||||
import {MatTreeModule} from "@angular/material/tree";
|
||||
import { TaskgroupOverviewComponent } from './dashboard/taskgroup-overview/taskgroup-overview.component';
|
||||
import { TaskOverviewComponent } from './dashboard/task-overview/task-overview.component';
|
||||
@NgModule({
|
||||
declarations: [
|
||||
AppComponent,
|
||||
@ -88,43 +93,48 @@ import { ScheduleDashboardComponent } from './schedules/schedule-dashboard/sched
|
||||
TaskDetailOverviewComponent,
|
||||
SchedulerComponent,
|
||||
BasicSchedulerComponent,
|
||||
ScheduleDashboardComponent
|
||||
],
|
||||
imports: [
|
||||
BrowserModule,
|
||||
AppRoutingModule,
|
||||
FormsModule,
|
||||
ApiModule,
|
||||
HttpClientModule,
|
||||
BrowserAnimationsModule,
|
||||
MatToolbarModule,
|
||||
MatButtonModule,
|
||||
MatIconModule,
|
||||
MatDialogModule,
|
||||
MatFormFieldModule,
|
||||
MatInputModule,
|
||||
MatProgressSpinnerModule,
|
||||
MatSnackBarModule,
|
||||
MatMenuModule,
|
||||
MatTabsModule,
|
||||
MatTableModule,
|
||||
MatCheckboxModule,
|
||||
MatCardModule,
|
||||
ReactiveFormsModule,
|
||||
MatListModule,
|
||||
MatDatepickerModule,
|
||||
MatInputModule,
|
||||
MatDatepickerModule,
|
||||
MatMomentDateModule,
|
||||
FormsModule,
|
||||
MatSlideToggleModule,
|
||||
MatSortModule,
|
||||
MatPaginatorModule,
|
||||
MatProgressBarModule,
|
||||
MatExpansionModule,
|
||||
CalendarModule.forRoot({provide: DateAdapter, useFactory: adapterFactory}),
|
||||
MatSelectModule
|
||||
ScheduleDashboardComponent,
|
||||
DashboardComponent,
|
||||
ActiveScheduleComponent,
|
||||
TaskgroupOverviewComponent,
|
||||
TaskOverviewComponent
|
||||
],
|
||||
imports: [
|
||||
BrowserModule,
|
||||
AppRoutingModule,
|
||||
FormsModule,
|
||||
ApiModule,
|
||||
HttpClientModule,
|
||||
BrowserAnimationsModule,
|
||||
MatToolbarModule,
|
||||
MatButtonModule,
|
||||
MatIconModule,
|
||||
MatDialogModule,
|
||||
MatFormFieldModule,
|
||||
MatInputModule,
|
||||
MatProgressSpinnerModule,
|
||||
MatSnackBarModule,
|
||||
MatMenuModule,
|
||||
MatTabsModule,
|
||||
MatTableModule,
|
||||
MatCheckboxModule,
|
||||
MatCardModule,
|
||||
ReactiveFormsModule,
|
||||
MatListModule,
|
||||
MatDatepickerModule,
|
||||
MatInputModule,
|
||||
MatDatepickerModule,
|
||||
MatMomentDateModule,
|
||||
FormsModule,
|
||||
MatSlideToggleModule,
|
||||
MatSortModule,
|
||||
MatPaginatorModule,
|
||||
MatProgressBarModule,
|
||||
MatExpansionModule,
|
||||
CalendarModule.forRoot({provide: DateAdapter, useFactory: adapterFactory}),
|
||||
MatSelectModule,
|
||||
MatTreeModule
|
||||
],
|
||||
providers: [
|
||||
HttpClientModule,
|
||||
/*
|
||||
|
@ -0,0 +1,6 @@
|
||||
import {ScheduleInfo} from "../../../api";
|
||||
|
||||
export interface StopActiveScheduleInfo {
|
||||
schedule: ScheduleInfo
|
||||
workedMinutes: number
|
||||
}
|
@ -0,0 +1,141 @@
|
||||
.container {
|
||||
margin: 20px auto;
|
||||
width: 70%;
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.spacer {
|
||||
margin-bottom: 2.5%;
|
||||
}
|
||||
|
||||
|
||||
@media screen and (max-width: 600px) {
|
||||
.container {
|
||||
width: 100%;
|
||||
margin: 20px 10px;
|
||||
}
|
||||
}
|
||||
|
||||
.today-worked-info {
|
||||
margin-left: 20px;
|
||||
background-color: #e1e1e1;
|
||||
padding-right: 5px;
|
||||
padding-left: 5px;
|
||||
border-radius: 5px;
|
||||
}
|
||||
|
||||
.red-card {
|
||||
background-color: #e54c3c;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.green-card {
|
||||
background-color: #00bc8c;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.main-container {
|
||||
width: 45%;
|
||||
margin-right: 20px;
|
||||
}
|
||||
|
||||
.btn-link {
|
||||
text-decoration: underline;
|
||||
color: white;
|
||||
margin-left: 20px;
|
||||
}
|
||||
|
||||
.dashboard-heading {
|
||||
margin-top: 20px;
|
||||
font-size: 2.5em;
|
||||
}
|
||||
|
||||
.today-worked-info {
|
||||
font-size: .8em;
|
||||
}
|
||||
|
||||
|
||||
.lightBlueBtn {
|
||||
background-color: #3498db;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.grayBtn {
|
||||
background-color: #444444;
|
||||
color: white;
|
||||
border-radius: 0;
|
||||
}
|
||||
|
||||
::ng-deep .mat-mdc-list-base {
|
||||
--mdc-list-list-item-label-text-color: white
|
||||
}
|
||||
|
||||
::ng-deep .mat-mdc-list-base .taskgroup-btn, ::ng-deep .mat-mdc-list-base .taskgroup-last-btn {
|
||||
--mdc-list-list-item-label-text-color: black
|
||||
}
|
||||
|
||||
.taskgroup-overview {
|
||||
width: 25%;
|
||||
float: right;
|
||||
}
|
||||
|
||||
.spacer {
|
||||
flex: 1 1 auto;
|
||||
}
|
||||
|
||||
.taskgroup-btn {
|
||||
background-color: #f3f3f3;
|
||||
border: 0 solid #000000;
|
||||
border-bottom-width: 1px;
|
||||
}
|
||||
|
||||
.taskgroup-last-btn {
|
||||
background-color: #f3f3f3;
|
||||
}
|
||||
|
||||
.link-no-deco {
|
||||
text-decoration: none;
|
||||
color: black;
|
||||
}
|
||||
|
||||
.link-no-deco:hover{
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
.gray-text {
|
||||
color: #6e6e6e;
|
||||
}
|
||||
|
||||
.yellowBtn {
|
||||
background-color: #f39c12;
|
||||
color: white;
|
||||
border-radius: 0;
|
||||
}
|
||||
|
||||
.primaryBtn {
|
||||
border-radius: 0;
|
||||
}
|
||||
|
||||
|
||||
::ng-deep .mat-mdc-card-header-text {
|
||||
display: block;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.schedule-del-btn {
|
||||
margin-top: 10px;
|
||||
}
|
||||
|
||||
.left-actions {
|
||||
float: left;
|
||||
}
|
||||
|
||||
.right-actions {
|
||||
float: right;
|
||||
}
|
||||
|
||||
.greenBtn {
|
||||
background-color: #00bc8c;
|
||||
color: white;
|
||||
border-radius: 0;
|
||||
}
|
@ -0,0 +1,19 @@
|
||||
<mat-card class="green-card" *ngIf="activeSchedule == undefined">
|
||||
<mat-card-content>
|
||||
<p>Currently there is no task in progress.</p>
|
||||
<a class="btn-link" routerLink="/">Did you forget to start an activity?</a>
|
||||
</mat-card-content>
|
||||
</mat-card>
|
||||
<mat-card *ngIf="activeSchedule != undefined">
|
||||
<mat-card-header>
|
||||
<mat-card-title><a routerLink="/" class="link-no-deco">{{activeSchedule!.task.taskName}}</a></mat-card-title>
|
||||
</mat-card-header>
|
||||
<mat-card-content>
|
||||
<span *ngFor="let taskgroupPath of activeSchedule!.taskgroupPath">{{taskgroupPath.taskgroupName}} /</span>
|
||||
<p class="gray-text" *ngIf="activeSchedule!.scheduleType==='BASIC'">Running for {{displayTime}}</p>
|
||||
</mat-card-content>
|
||||
<mat-card-actions>
|
||||
<button mat-raised-button class="grayBtn" (click)="stopTask(false)">Stop</button>
|
||||
<button mat-raised-button class="greenBtn" (click)="stopTask(true)">Finish</button>
|
||||
</mat-card-actions>
|
||||
</mat-card>
|
@ -0,0 +1,21 @@
|
||||
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
|
||||
import { ActiveScheduleComponent } from './active-schedule.component';
|
||||
|
||||
describe('ActiveScheduleComponent', () => {
|
||||
let component: ActiveScheduleComponent;
|
||||
let fixture: ComponentFixture<ActiveScheduleComponent>;
|
||||
|
||||
beforeEach(() => {
|
||||
TestBed.configureTestingModule({
|
||||
declarations: [ActiveScheduleComponent]
|
||||
});
|
||||
fixture = TestBed.createComponent(ActiveScheduleComponent);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
@ -0,0 +1,77 @@
|
||||
import {Component, EventEmitter, Input, OnInit, Output} from '@angular/core';
|
||||
import {ScheduleInfo, ScheduleService, TaskOverviewInfo} from "../../../api";
|
||||
import {StopActiveScheduleInfo} from "./StopActiveScheduleInfo";
|
||||
import {TaskOverviewComponent} from "../task-overview/task-overview.component";
|
||||
|
||||
@Component({
|
||||
selector: 'app-active-schedule',
|
||||
templateUrl: './active-schedule.component.html',
|
||||
styleUrls: ['./active-schedule.component.css']
|
||||
})
|
||||
export class ActiveScheduleComponent implements OnInit{
|
||||
activeSchedule: ScheduleInfo | undefined
|
||||
|
||||
startTime: number = 0;
|
||||
currentTime: number = 0;
|
||||
displayTime: string = "00:00:00"
|
||||
|
||||
@Output('onStopTask') scheduleStopEmitter = new EventEmitter<StopActiveScheduleInfo>;
|
||||
|
||||
constructor(private scheduleService: ScheduleService) {
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
updateTime() {
|
||||
const now = Date.now();
|
||||
const elapsed = this.activeSchedule != undefined ? now - this.startTime + this.currentTime : this.currentTime;
|
||||
this.displayTime = this.formatTime(elapsed);
|
||||
requestAnimationFrame(() => this.updateTime());
|
||||
}
|
||||
|
||||
formatTime(milliseconds: number): string {
|
||||
const seconds = Math.floor((milliseconds / 1000) % 60);
|
||||
const minutes = Math.floor((milliseconds / 1000 / 60) % 60);
|
||||
const hours = Math.floor(milliseconds / 1000 / 60 / 60);
|
||||
return `${this.padNumber(hours)}:${this.padNumber(minutes)}:${this.padNumber(seconds)}`;
|
||||
}
|
||||
padNumber(num: number): string {
|
||||
return num < 10 ? `0${num}` : `${num}`;
|
||||
}
|
||||
|
||||
ngOnInit(): void {
|
||||
this.scheduleService.schedulesActiveGet().subscribe({
|
||||
next: resp => {
|
||||
if(resp.scheduleID >= 0) {
|
||||
this.activateSchedule(resp);
|
||||
}
|
||||
|
||||
},
|
||||
|
||||
})
|
||||
}
|
||||
|
||||
stopTask(finish: boolean) {
|
||||
this.scheduleService.schedulesScheduleIDStopFinishPost(this.activeSchedule!.scheduleID, finish).subscribe({
|
||||
next: resp => {
|
||||
this.scheduleStopEmitter.emit({
|
||||
schedule: this.activeSchedule!,
|
||||
workedMinutes: resp.workTime
|
||||
})
|
||||
this.activeSchedule = undefined
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
activateSchedule(schedule: ScheduleInfo) {
|
||||
this.activeSchedule = schedule;
|
||||
this.startTime = new Date(this.activeSchedule.startTime).getTime();
|
||||
this.updateTime();
|
||||
}
|
||||
|
||||
finishTaskByOverview(task: TaskOverviewInfo) {
|
||||
this.activeSchedule = undefined
|
||||
}
|
||||
|
||||
}
|
143
frontend/src/app/dashboard/dashboard.component.css
Normal file
143
frontend/src/app/dashboard/dashboard.component.css
Normal file
@ -0,0 +1,143 @@
|
||||
.container {
|
||||
margin: 20px auto;
|
||||
width: 70%;
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.spacer {
|
||||
margin-bottom: 2.5%;
|
||||
}
|
||||
|
||||
|
||||
@media screen and (max-width: 600px) {
|
||||
.container {
|
||||
width: 100%;
|
||||
margin: 20px 10px;
|
||||
}
|
||||
}
|
||||
|
||||
.today-worked-info {
|
||||
margin-left: 20px;
|
||||
background-color: #e1e1e1;
|
||||
padding-right: 5px;
|
||||
padding-left: 5px;
|
||||
border-radius: 5px;
|
||||
}
|
||||
|
||||
.red-card {
|
||||
background-color: #e54c3c;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.green-card {
|
||||
background-color: #00bc8c;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.main-container {
|
||||
width: 45%;
|
||||
margin-right: 20px;
|
||||
}
|
||||
|
||||
.btn-link {
|
||||
text-decoration: underline;
|
||||
color: white;
|
||||
margin-left: 20px;
|
||||
}
|
||||
|
||||
.dashboard-heading {
|
||||
margin-top: 20px;
|
||||
font-size: 2.5em;
|
||||
}
|
||||
|
||||
.today-worked-info {
|
||||
font-size: .8em;
|
||||
}
|
||||
|
||||
|
||||
.lightBlueBtn {
|
||||
background-color: #3498db;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.grayBtn {
|
||||
background-color: #444444;
|
||||
color: white;
|
||||
border-radius: 0;
|
||||
}
|
||||
|
||||
::ng-deep .mat-mdc-list-base {
|
||||
--mdc-list-list-item-label-text-color: white
|
||||
}
|
||||
|
||||
::ng-deep .mat-mdc-list-base .taskgroup-btn, ::ng-deep .mat-mdc-list-base .taskgroup-last-btn {
|
||||
--mdc-list-list-item-label-text-color: black
|
||||
}
|
||||
|
||||
.taskgroup-overview {
|
||||
width: 35%;
|
||||
float: right;
|
||||
margin-right: 20px;
|
||||
}
|
||||
|
||||
.spacer {
|
||||
flex: 1 1 auto;
|
||||
}
|
||||
|
||||
.taskgroup-btn {
|
||||
background-color: #f3f3f3;
|
||||
border: 0 solid #000000;
|
||||
border-bottom-width: 1px;
|
||||
}
|
||||
|
||||
.taskgroup-last-btn {
|
||||
background-color: #f3f3f3;
|
||||
}
|
||||
|
||||
.link-no-deco {
|
||||
text-decoration: none;
|
||||
color: black;
|
||||
}
|
||||
|
||||
.link-no-deco:hover{
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
.gray-text {
|
||||
color: #6e6e6e;
|
||||
}
|
||||
|
||||
.yellowBtn {
|
||||
background-color: #f39c12;
|
||||
color: white;
|
||||
border-radius: 0;
|
||||
}
|
||||
|
||||
.primaryBtn {
|
||||
border-radius: 0;
|
||||
}
|
||||
|
||||
|
||||
::ng-deep .mat-mdc-card-header-text {
|
||||
display: block;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.schedule-del-btn {
|
||||
margin-top: 10px;
|
||||
}
|
||||
|
||||
.left-actions {
|
||||
float: left;
|
||||
}
|
||||
|
||||
.right-actions {
|
||||
float: right;
|
||||
}
|
||||
|
||||
.taskgroup-first-child {
|
||||
background-color: #f3f3f3;
|
||||
border: 0 solid #000000;
|
||||
border-top-width: 1px;
|
||||
border-bottom-width: 1px;
|
||||
}
|
51
frontend/src/app/dashboard/dashboard.component.html
Normal file
51
frontend/src/app/dashboard/dashboard.component.html
Normal file
@ -0,0 +1,51 @@
|
||||
<div class="container">
|
||||
<div class="main-container">
|
||||
<mat-card *ngIf="missedSchedules" class="red-card">
|
||||
<mat-card-content>
|
||||
<p>There are missed schedules. Please reschedule them.</p>
|
||||
<a class="btn-link" routerLink="/">Reschedule</a>
|
||||
</mat-card-content>
|
||||
</mat-card>
|
||||
<h1 class="dashboard-heading">Now<b class="today-worked-info">Today: {{workedMinutesToday}} min</b></h1>
|
||||
|
||||
<app-active-schedule #activeSchedule (onStopTask)="stopedTask($event)"></app-active-schedule>
|
||||
|
||||
<h1 class="dashboard-heading">Scheduled for today</h1>
|
||||
<mat-card class="green-card" *ngIf="schedules.length == 0">
|
||||
<mat-card-content>
|
||||
<p>There is no scheduled Task for today</p>
|
||||
</mat-card-content>
|
||||
</mat-card>
|
||||
|
||||
|
||||
|
||||
<div>
|
||||
<mat-card *ngFor="let schedule of schedules">
|
||||
<mat-card-header>
|
||||
<mat-card-title>
|
||||
<a routerLink="/" class="link-no-deco">{{schedule.task.taskName}}</a>
|
||||
</mat-card-title>
|
||||
</mat-card-header>
|
||||
<mat-card-content>
|
||||
<span *ngFor="let taskgroupPath of schedule.taskgroupPath">{{taskgroupPath.taskgroupName}} /</span>
|
||||
<p class="gray-text" *ngIf="schedule.scheduleType==='BASIC'">To be done sometime today</p>
|
||||
</mat-card-content>
|
||||
<mat-card-actions>
|
||||
<button mat-raised-button color="primary" class="primaryBtn" (click)="startSchedule(schedule)" [disabled]="activeScheduleComponent!.activeSchedule != undefined">Start now</button>
|
||||
<button mat-raised-button class="yellowBtn">Reschedule</button>
|
||||
</mat-card-actions>
|
||||
</mat-card>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<div class="taskgroup-overview">
|
||||
<app-task-overview [tasks]="tasks" (onStartNow)="onStartTaskNow($event)" [taskgroupID]="selectedTaskgroupID" (onFinished)="onFinishTask($event)"></app-task-overview>
|
||||
</div>
|
||||
|
||||
<div class="taskgroup-overview">
|
||||
|
||||
<app-taskgroup-overview (taskgroupSelected)="onSelectTaskgroup($event)"></app-taskgroup-overview>
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
21
frontend/src/app/dashboard/dashboard.component.spec.ts
Normal file
21
frontend/src/app/dashboard/dashboard.component.spec.ts
Normal file
@ -0,0 +1,21 @@
|
||||
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
|
||||
import { DashboardComponent } from './dashboard.component';
|
||||
|
||||
describe('DashboardComponent', () => {
|
||||
let component: DashboardComponent;
|
||||
let fixture: ComponentFixture<DashboardComponent>;
|
||||
|
||||
beforeEach(() => {
|
||||
TestBed.configureTestingModule({
|
||||
declarations: [DashboardComponent]
|
||||
});
|
||||
fixture = TestBed.createComponent(DashboardComponent);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
75
frontend/src/app/dashboard/dashboard.component.ts
Normal file
75
frontend/src/app/dashboard/dashboard.component.ts
Normal file
@ -0,0 +1,75 @@
|
||||
import {Component, OnInit, ViewChild} from '@angular/core';
|
||||
import {BasicScheduleEntityInfo, ScheduleInfo, ScheduleService, TaskOverviewInfo} from "../../api";
|
||||
import {ActiveScheduleComponent} from "./active-schedule/active-schedule.component";
|
||||
import {StopActiveScheduleInfo} from "./active-schedule/StopActiveScheduleInfo";
|
||||
import {TaskOverviewComponent} from "./task-overview/task-overview.component";
|
||||
import {TaskOverviewData} from "./taskgroup-overview/taskgroup-overview.component";
|
||||
|
||||
@Component({
|
||||
selector: 'app-dashboard',
|
||||
templateUrl: './dashboard.component.html',
|
||||
styleUrls: ['./dashboard.component.css']
|
||||
})
|
||||
export class DashboardComponent implements OnInit{
|
||||
|
||||
missedSchedules: boolean = true
|
||||
schedules: ScheduleInfo[] = []
|
||||
workedMinutesToday: number = 0
|
||||
|
||||
tasks: TaskOverviewInfo[] = []
|
||||
selectedTaskgroupID: number | undefined
|
||||
|
||||
@ViewChild('activeSchedule') activeScheduleComponent: ActiveScheduleComponent | undefined
|
||||
constructor(private scheduleService: ScheduleService) {
|
||||
}
|
||||
|
||||
ngOnInit() {
|
||||
this.scheduleService.schedulesTodayActivateableGet(true).subscribe({
|
||||
next: resp => {
|
||||
this.schedules = resp;
|
||||
}
|
||||
})
|
||||
|
||||
this.scheduleService.schedulesStatusTodayGet().subscribe({
|
||||
next: resp => {
|
||||
this.workedMinutesToday = resp.activeMinutes;
|
||||
this.missedSchedules = resp.missedSchedules;
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
startSchedule(schedule: ScheduleInfo) {
|
||||
this.scheduleService.schedulesScheduleIDActivatePost(schedule.scheduleID).subscribe({
|
||||
next: resp => {
|
||||
schedule.startTime = resp.startTime;
|
||||
if(this.activeScheduleComponent != undefined) {
|
||||
this.activeScheduleComponent.activateSchedule(schedule);
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
stopedTask(stopActiveScheduleInfo: StopActiveScheduleInfo) {
|
||||
this.workedMinutesToday += stopActiveScheduleInfo.workedMinutes;
|
||||
this.schedules = this.schedules.filter(schedule => schedule.scheduleID !== stopActiveScheduleInfo.schedule.scheduleID);
|
||||
}
|
||||
|
||||
|
||||
protected readonly TaskOverviewComponent = TaskOverviewComponent;
|
||||
|
||||
onSelectTaskgroup(taskOverviewData: TaskOverviewData) {
|
||||
this.tasks = taskOverviewData.tasks;
|
||||
this.selectedTaskgroupID = taskOverviewData.taskgroupID;
|
||||
}
|
||||
|
||||
onStartTaskNow(schedule: ScheduleInfo) {
|
||||
this.activeScheduleComponent?.activateSchedule(schedule)
|
||||
}
|
||||
|
||||
onFinishTask(task: TaskOverviewInfo) {
|
||||
this.activeScheduleComponent?.finishTaskByOverview(task);
|
||||
|
||||
this.schedules = this.schedules.filter(schedule => schedule.task.taskID !== task.taskID)
|
||||
}
|
||||
}
|
@ -0,0 +1,33 @@
|
||||
.greenBtn {
|
||||
background-color: #00bc8c;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.btn-without-radius {
|
||||
border-radius: 0;
|
||||
}
|
||||
|
||||
.task-info {
|
||||
line-height: .75em;
|
||||
}
|
||||
|
||||
.progress {
|
||||
margin-bottom: 10px;
|
||||
margin-top: -5px;
|
||||
}
|
||||
|
||||
.long-btn {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
|
||||
.yellowBtn {
|
||||
background-color: #f39c12;
|
||||
color: white;
|
||||
border-radius: 0;
|
||||
}
|
||||
|
||||
.task-link {
|
||||
text-decoration: none;
|
||||
color: black;
|
||||
}
|
@ -0,0 +1,14 @@
|
||||
<button mat-raised-button class="greenBtn long-btn" *ngIf="taskgroupID != undefined" (click)="openTaskCreation()">Add</button>
|
||||
<mat-card *ngFor="let task of tasks">
|
||||
<mat-card-content>
|
||||
<h3><a class="task-link" [routerLink]="['/taskgroups', taskgroupID!, 'tasks', task.taskID]">{{task.taskName}}</a></h3>
|
||||
<mat-progress-bar mode="determinate" value="{{task.activeTime}}" class="progress"></mat-progress-bar>
|
||||
<p class="task-info"><i>ETA: </i>{{task.activeTime}} / {{task.eta}}</p>
|
||||
<p class="task-info"><i>Limit: </i>{{task.limit}}</p>
|
||||
</mat-card-content>
|
||||
<mat-card-actions>
|
||||
<button mat-raised-button color="primary" class="btn-without-radius" (click)="startTaskNow(task)">Start now</button>
|
||||
<button *ngIf="taskgroupID != undefined" mat-raised-button class="yellowBtn btn-without-radius" [routerLink]="['/taskgroups', taskgroupID!, 'tasks', task.taskID, 'schedule']">Schedule</button>
|
||||
<button mat-raised-button class="greenBtn btn-without-radius" (click)="finishTask(task)">Finish</button>
|
||||
</mat-card-actions>
|
||||
</mat-card>
|
@ -0,0 +1,21 @@
|
||||
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
|
||||
import { TaskOverviewComponent } from './task-overview.component';
|
||||
|
||||
describe('TaskOverviewComponent', () => {
|
||||
let component: TaskOverviewComponent;
|
||||
let fixture: ComponentFixture<TaskOverviewComponent>;
|
||||
|
||||
beforeEach(() => {
|
||||
TestBed.configureTestingModule({
|
||||
declarations: [TaskOverviewComponent]
|
||||
});
|
||||
fixture = TestBed.createComponent(TaskOverviewComponent);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
@ -0,0 +1,82 @@
|
||||
import {Component, EventEmitter, Input, Output} from '@angular/core';
|
||||
import {BasicScheduleEntityInfo, ScheduleInfo, ScheduleService, TaskOverviewInfo, TaskService} from "../../../api";
|
||||
import {MatSnackBar} from "@angular/material/snack-bar";
|
||||
import {TaskEditorData} from "../../tasks/task-editor/TaskEditorData";
|
||||
import {TaskEditorComponent} from "../../tasks/task-editor/task-editor.component";
|
||||
import {MatDialog} from "@angular/material/dialog";
|
||||
|
||||
@Component({
|
||||
selector: 'app-task-overview',
|
||||
templateUrl: './task-overview.component.html',
|
||||
styleUrls: ['./task-overview.component.css']
|
||||
})
|
||||
export class TaskOverviewComponent {
|
||||
|
||||
@Input() tasks: TaskOverviewInfo[] = []
|
||||
@Input() taskgroupID: number | undefined
|
||||
@Output('onStartNow') startNowEmitter: EventEmitter<ScheduleInfo> = new EventEmitter<ScheduleInfo>();
|
||||
@Output('onFinished') finishedEmitter: EventEmitter<TaskOverviewInfo> = new EventEmitter<TaskOverviewInfo>();
|
||||
|
||||
constructor(private scheduleService: ScheduleService,
|
||||
private snackbar: MatSnackBar,
|
||||
private taskService: TaskService,
|
||||
private dialog: MatDialog) {
|
||||
|
||||
}
|
||||
startTaskNow(task: TaskOverviewInfo) {
|
||||
this.scheduleService.schedulesTaskIDNowPost(task.taskID).subscribe({
|
||||
next: resp => {
|
||||
this.startNowEmitter.emit(resp);
|
||||
},
|
||||
error: err => {
|
||||
if(err.status == 403) {
|
||||
this.snackbar.open("No permission", "", {duration: 2000});
|
||||
} else if(err.status == 404) {
|
||||
this.snackbar.open("Task not found", "", {duration: 2000});
|
||||
} else if(err.status == 409) {
|
||||
this.snackbar.open("Task is already running", "", {duration: 2000});
|
||||
} else {
|
||||
this.snackbar.open("Unexpected error", "", {duration: 2000});
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
finishTask(task: TaskOverviewInfo) {
|
||||
this.taskService.tasksTaskIDFinishPost(task.taskID).subscribe({
|
||||
next: resp => {
|
||||
this.finishedEmitter.emit(task);
|
||||
this.tasks = this.tasks.filter(ct => ct.taskID !== task.taskID)
|
||||
},
|
||||
error: err => {
|
||||
if(err.status == 403) {
|
||||
this.snackbar.open("No permission", "", {duration: 2000});
|
||||
} else if(err.status == 404) {
|
||||
this.snackbar.open("Task not found", "", {duration: 2000});
|
||||
} else {
|
||||
this.snackbar.open("Unexpected error", "", {duration: 2000});
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
openTaskCreation() {
|
||||
const editorData: TaskEditorData = {
|
||||
task: undefined,
|
||||
taskgroupID: this.taskgroupID!
|
||||
}
|
||||
const dialogRef = this.dialog.open(TaskEditorComponent, {data: editorData, width: "600px"})
|
||||
dialogRef.afterClosed().subscribe(res => {
|
||||
if(res != undefined) {
|
||||
this.tasks.push({
|
||||
taskID: res.taskID,
|
||||
eta: res.eta,
|
||||
limit: res.deadline,
|
||||
taskName: res.taskName,
|
||||
activeTime: 0,
|
||||
overdue: res.overdue
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
@ -0,0 +1,167 @@
|
||||
.container {
|
||||
margin: 20px auto;
|
||||
width: 70%;
|
||||
}
|
||||
|
||||
.spacer {
|
||||
flex: 1 1 auto;
|
||||
}
|
||||
|
||||
|
||||
@media screen and (max-width: 600px) {
|
||||
.container {
|
||||
width: 100%;
|
||||
margin: 20px 10px;
|
||||
}
|
||||
}
|
||||
|
||||
.today-worked-info {
|
||||
margin-left: 20px;
|
||||
background-color: #e1e1e1;
|
||||
padding-right: 5px;
|
||||
padding-left: 5px;
|
||||
border-radius: 5px;
|
||||
}
|
||||
|
||||
.red-card {
|
||||
background-color: #e54c3c;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.green-card {
|
||||
background-color: #00bc8c;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.main-container {
|
||||
width: 45%;
|
||||
margin-right: 20px;
|
||||
}
|
||||
|
||||
.btn-link {
|
||||
text-decoration: underline;
|
||||
color: white;
|
||||
margin-left: 20px;
|
||||
}
|
||||
|
||||
.dashboard-heading {
|
||||
margin-top: 20px;
|
||||
font-size: 2.5em;
|
||||
}
|
||||
|
||||
.today-worked-info {
|
||||
font-size: .8em;
|
||||
}
|
||||
|
||||
|
||||
.lightBlueBtn {
|
||||
background-color: #3498db;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.grayBtn {
|
||||
background-color: #444444;
|
||||
color: white;
|
||||
border-radius: 0;
|
||||
}
|
||||
|
||||
::ng-deep .mat-mdc-list-base {
|
||||
--mdc-list-list-item-label-text-color: white
|
||||
}
|
||||
|
||||
::ng-deep .mat-mdc-list-base .taskgroup-btn, ::ng-deep .mat-mdc-list-base .taskgroup-last-btn {
|
||||
--mdc-list-list-item-label-text-color: black
|
||||
}
|
||||
|
||||
.taskgroup-overview {
|
||||
width: 25%;
|
||||
float: right;
|
||||
}
|
||||
|
||||
.spacer {
|
||||
flex: 1 1 auto;
|
||||
}
|
||||
|
||||
.taskgroup-btn {
|
||||
background-color: #f3f3f3;
|
||||
border: 0 solid #000000;
|
||||
border-bottom-width: 1px;
|
||||
}
|
||||
|
||||
.taskgroup-last-btn {
|
||||
background-color: #f3f3f3;
|
||||
}
|
||||
|
||||
.link-no-deco {
|
||||
text-decoration: none;
|
||||
color: black;
|
||||
}
|
||||
|
||||
.link-no-deco:hover{
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
.gray-text {
|
||||
color: #6e6e6e;
|
||||
}
|
||||
|
||||
.yellowBtn {
|
||||
background-color: #f39c12;
|
||||
color: white;
|
||||
border-radius: 0;
|
||||
}
|
||||
|
||||
.primaryBtn {
|
||||
border-radius: 0;
|
||||
}
|
||||
|
||||
|
||||
::ng-deep .mat-mdc-card-header-text {
|
||||
display: block;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.schedule-del-btn {
|
||||
margin-top: 10px;
|
||||
}
|
||||
|
||||
.left-actions {
|
||||
float: left;
|
||||
}
|
||||
|
||||
.right-actions {
|
||||
float: right;
|
||||
}
|
||||
|
||||
.taskgroup-first-child {
|
||||
background-color: #f3f3f3;
|
||||
border: 0 solid #000000;
|
||||
border-top-width: 1px;
|
||||
border-bottom-width: 1px;
|
||||
}
|
||||
|
||||
.node-name {
|
||||
font-style: normal;
|
||||
font-weight: normal;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.task-number{
|
||||
color: white;
|
||||
background-color: deepskyblue;
|
||||
padding: 1px 10px;
|
||||
border-radius: 5px;
|
||||
margin-right: 5px;
|
||||
}
|
||||
|
||||
.treenode-content-container {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.overdue-taskgroup {
|
||||
background-color: #ff695b;
|
||||
}
|
@ -0,0 +1,29 @@
|
||||
<mat-action-list style="padding: 0">
|
||||
<button mat-list-item class="lightBlueBtn" [routerLink]="['/taskgroups']">Manage Taskgroups</button>
|
||||
</mat-action-list>
|
||||
<mat-tree [dataSource]="dataSource" [treeControl]="treeControl" >
|
||||
<!-- This is the tree node template for leaf nodes -->
|
||||
<mat-tree-node *matTreeNodeDef="let node" matTreeNodePadding class="taskgroup-btn" matTreeNodePaddingIndent="10" [ngClass]="node.hasOverdueTask? 'overdue-taskgroup':''">
|
||||
<!-- use a disabled button to provide padding for tree leaf -->
|
||||
<button mat-icon-button disabled></button>
|
||||
<div class="treenode-content-container">
|
||||
<button mat-button class="node-name" (click)="onSelectTaskgroup(node.tasks, node.taskgroupID)">{{node.name}}</button>
|
||||
<span class="spacer"></span>
|
||||
<div class="task-number">{{node.activeTasks}}</div>
|
||||
</div>
|
||||
</mat-tree-node>
|
||||
<!-- This is the tree node template for expandable nodes -->
|
||||
<mat-tree-node *matTreeNodeDef="let node;when: hasChild" matTreeNodePadding class="taskgroup-btn" matTreeNodePaddingIndent="10" [ngClass]="node.hasOverdueTask? 'overdue-taskgroup':''">
|
||||
<button mat-icon-button matTreeNodeToggle
|
||||
[attr.aria-label]="'Toggle ' + node.name" style="padding-left: 10px">
|
||||
<mat-icon class="mat-icon-rtl-mirror">
|
||||
{{treeControl.isExpanded(node) ? 'expand_more' : 'chevron_right'}}
|
||||
</mat-icon>
|
||||
</button>
|
||||
<div class="treenode-content-container">
|
||||
<button mat-button class="node-name" (click)="onSelectTaskgroup(node.tasks, node.taskgroupID)">{{node.name}}</button>
|
||||
<span class="spacer"></span>
|
||||
<div class="task-number">{{node.activeTasks}}</div>
|
||||
</div>
|
||||
</mat-tree-node>
|
||||
</mat-tree>
|
@ -0,0 +1,21 @@
|
||||
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
|
||||
import { TaskgroupOverviewComponent } from './taskgroup-overview.component';
|
||||
|
||||
describe('TaskgroupOverviewComponent', () => {
|
||||
let component: TaskgroupOverviewComponent;
|
||||
let fixture: ComponentFixture<TaskgroupOverviewComponent>;
|
||||
|
||||
beforeEach(() => {
|
||||
TestBed.configureTestingModule({
|
||||
declarations: [TaskgroupOverviewComponent]
|
||||
});
|
||||
fixture = TestBed.createComponent(TaskgroupOverviewComponent);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
@ -0,0 +1,81 @@
|
||||
import {Component, EventEmitter, Output} from '@angular/core';
|
||||
import {MatIconModule} from "@angular/material/icon";
|
||||
import {MatButtonModule} from "@angular/material/button";
|
||||
import {MatTreeFlatDataSource, MatTreeFlattener, MatTreeModule} from "@angular/material/tree";
|
||||
import {FlatTreeControl} from "@angular/cdk/tree";
|
||||
import {RecursiveTaskgroupInfo, TaskgroupService, TaskOverviewInfo} from "../../../api";
|
||||
import {TaskOverviewComponent} from "../task-overview/task-overview.component";
|
||||
|
||||
|
||||
|
||||
|
||||
/** Flat node with expandable and level information */
|
||||
interface ExampleFlatNode {
|
||||
expandable: boolean;
|
||||
level: number;
|
||||
name: string
|
||||
activeTasks: number;
|
||||
hasOverdueTask: boolean;
|
||||
tasks: TaskOverviewInfo[];
|
||||
taskgroupID: number
|
||||
}
|
||||
|
||||
export interface TaskOverviewData {
|
||||
tasks: TaskOverviewInfo[],
|
||||
taskgroupID: number
|
||||
}
|
||||
@Component({
|
||||
selector: 'app-taskgroup-overview',
|
||||
templateUrl: './taskgroup-overview.component.html',
|
||||
styleUrls: ['./taskgroup-overview.component.css']
|
||||
})
|
||||
export class TaskgroupOverviewComponent {
|
||||
|
||||
@Output('taskgroupSelected') taskgroupSelected: EventEmitter<TaskOverviewData> = new EventEmitter<TaskOverviewData>();
|
||||
private _transformer = (node: RecursiveTaskgroupInfo, level: number) => {
|
||||
return {
|
||||
expandable: !!node.childTaskgroups && node.childTaskgroups.length > 0,
|
||||
name: node.taskgroupName,
|
||||
level: level,
|
||||
activeTasks: node.amountActiveTasks,
|
||||
hasOverdueTask: node.hasOverdueTask,
|
||||
tasks: node.activeTasks,
|
||||
taskgroupID: node.taskgroupID
|
||||
};
|
||||
};
|
||||
|
||||
treeControl = new FlatTreeControl<ExampleFlatNode>(
|
||||
node => node.level,
|
||||
node => node.expandable,
|
||||
);
|
||||
|
||||
treeFlattener = new MatTreeFlattener(
|
||||
this._transformer,
|
||||
node => node.level,
|
||||
node => node.expandable,
|
||||
node => node.childTaskgroups,
|
||||
);
|
||||
|
||||
dataSource = new MatTreeFlatDataSource(this.treeControl, this.treeFlattener);
|
||||
|
||||
constructor(private taskgroupService: TaskgroupService) {
|
||||
|
||||
}
|
||||
|
||||
ngOnInit() {
|
||||
this.taskgroupService.taskgroupsTreeGet().subscribe({
|
||||
next: resp => {
|
||||
this.dataSource.data = resp;
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
hasChild = (_: number, node: ExampleFlatNode) => node.expandable;
|
||||
|
||||
onSelectTaskgroup(tasks: TaskOverviewInfo[], taskgroupID: number) {
|
||||
this.taskgroupSelected.emit({
|
||||
tasks: tasks,
|
||||
taskgroupID: taskgroupID
|
||||
})
|
||||
}
|
||||
}
|
@ -0,0 +1 @@
|
||||
<app-dashboard></app-dashboard>
|
@ -29,7 +29,7 @@
|
||||
<ng-container matColumnDef="finished">
|
||||
<th mat-header-cell *matHeaderCellDef mat-sort-header> Finished </th>
|
||||
<td mat-cell *matCellDef="let task">
|
||||
<mat-checkbox [value]="task.finished" [contentEditable]="false" disableRipple="true" (click)="$event.preventDefault()"></mat-checkbox>
|
||||
<mat-checkbox [checked]="task.finished" [contentEditable]="false" disableRipple="true" (click)="$event.preventDefault()"></mat-checkbox>
|
||||
</td>
|
||||
</ng-container>
|
||||
<ng-container matColumnDef="status">
|
||||
|
@ -22,6 +22,8 @@ export class TaskDashboardComponent implements OnChanges{
|
||||
this.datasource = new MatTableDataSource<TaskEntityInfo>(resp);
|
||||
this.datasource.paginator = this.paginator!;
|
||||
this.datasource.sort = this.sort!;
|
||||
|
||||
resp.forEach(task => console.log(task))
|
||||
}
|
||||
})
|
||||
}
|
||||
|
311
openapi.yaml
311
openapi.yaml
@ -581,6 +581,23 @@ paths:
|
||||
type: array
|
||||
items:
|
||||
$ref: '#/components/schemas/TaskgroupEntityInfo'
|
||||
/taskgroups/tree:
|
||||
get:
|
||||
security:
|
||||
- API_TOKEN: []
|
||||
tags:
|
||||
- taskgroup
|
||||
summary: list all top level taskgroups of authorized user
|
||||
description: list all taskgroups of authorized user
|
||||
responses:
|
||||
200:
|
||||
description: Anfrage erfolgreich
|
||||
content:
|
||||
'application/json':
|
||||
schema:
|
||||
type: array
|
||||
items:
|
||||
$ref: '#/components/schemas/RecursiveTaskgroupInfo'
|
||||
/taskgroups:
|
||||
get:
|
||||
security:
|
||||
@ -1154,6 +1171,44 @@ paths:
|
||||
schema:
|
||||
type: object
|
||||
$ref: "#/components/schemas/SimpleStatusResponse"
|
||||
/tasks/{taskID}/finish:
|
||||
post:
|
||||
security:
|
||||
- API_TOKEN: []
|
||||
tags:
|
||||
- task
|
||||
summary: finishs task
|
||||
description: finish tasks
|
||||
parameters:
|
||||
- name: taskID
|
||||
in: path
|
||||
description: internal id of task
|
||||
required: true
|
||||
schema:
|
||||
type: number
|
||||
example: 1
|
||||
responses:
|
||||
200:
|
||||
description: Anfrage erfolgreich
|
||||
content:
|
||||
'application/json':
|
||||
schema:
|
||||
type: object
|
||||
$ref: "#/components/schemas/SimpleStatusResponse"
|
||||
403:
|
||||
description: No permission
|
||||
content:
|
||||
'application/json':
|
||||
schema:
|
||||
type: object
|
||||
$ref: "#/components/schemas/SimpleStatusResponse"
|
||||
404:
|
||||
description: Taskgroup does not exist
|
||||
content:
|
||||
'application/json':
|
||||
schema:
|
||||
type: object
|
||||
$ref: "#/components/schemas/SimpleStatusResponse"
|
||||
/schedules:
|
||||
get:
|
||||
security:
|
||||
@ -1355,7 +1410,7 @@ paths:
|
||||
schema:
|
||||
type: object
|
||||
$ref: "#/components/schemas/SimpleStatusResponse"
|
||||
/schedules/today:
|
||||
/schedules/today/{activateable}:
|
||||
get:
|
||||
security:
|
||||
- API_TOKEN: []
|
||||
@ -1363,6 +1418,15 @@ paths:
|
||||
- schedule
|
||||
description: get all schedules of today
|
||||
summary: get today's schedules
|
||||
parameters:
|
||||
- name: activateable
|
||||
in: path
|
||||
description: determines whether only schedules that can be started should be included or all schedules of today
|
||||
required: true
|
||||
schema:
|
||||
type: boolean
|
||||
example: true
|
||||
|
||||
responses:
|
||||
200:
|
||||
description: Operation successfull
|
||||
@ -1395,7 +1459,7 @@ paths:
|
||||
application/json:
|
||||
schema:
|
||||
type: object
|
||||
$ref: '#/components/schemas/BasicScheduleEntityInfo'
|
||||
$ref: '#/components/schemas/ScheduleInfo'
|
||||
403:
|
||||
description: No permission
|
||||
content:
|
||||
@ -1417,6 +1481,146 @@ paths:
|
||||
schema:
|
||||
type: object
|
||||
$ref: "#/components/schemas/SimpleStatusResponse"
|
||||
/schedules/active:
|
||||
get:
|
||||
security:
|
||||
- API_TOKEN: []
|
||||
tags:
|
||||
- schedule
|
||||
description: get active schedule
|
||||
summary: get active schedule
|
||||
responses:
|
||||
200:
|
||||
description: operation successfull
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/ScheduleInfo'
|
||||
404:
|
||||
description: there is no active schedule
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/SimpleStatusResponse'
|
||||
/schedules/{scheduleID}/activate:
|
||||
post:
|
||||
security:
|
||||
- API_TOKEN: []
|
||||
tags:
|
||||
- schedule
|
||||
description: activates schedule
|
||||
summary: activates schedule
|
||||
parameters:
|
||||
- name: scheduleID
|
||||
in: path
|
||||
description: internal id of schedule
|
||||
required: true
|
||||
schema:
|
||||
type: number
|
||||
example: 1
|
||||
responses:
|
||||
200:
|
||||
description: Operation successfull
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: object
|
||||
$ref: '#/components/schemas/ScheduleActivateInfo'
|
||||
403:
|
||||
description: No permission
|
||||
content:
|
||||
'application/json':
|
||||
schema:
|
||||
type: object
|
||||
$ref: "#/components/schemas/SimpleStatusResponse"
|
||||
404:
|
||||
description: Schedule does not exist
|
||||
content:
|
||||
'application/json':
|
||||
schema:
|
||||
type: object
|
||||
$ref: "#/components/schemas/SimpleStatusResponse"
|
||||
409:
|
||||
description: Task is already running
|
||||
content:
|
||||
'application/json':
|
||||
schema:
|
||||
type: object
|
||||
$ref: "#/components/schemas/SimpleStatusResponse"
|
||||
/schedules/{scheduleID}/stop/{finish}:
|
||||
post:
|
||||
security:
|
||||
- API_TOKEN: []
|
||||
tags:
|
||||
- schedule
|
||||
parameters:
|
||||
- name: scheduleID
|
||||
in: path
|
||||
description: internal id of schedule
|
||||
required: true
|
||||
schema:
|
||||
type: number
|
||||
example: 1
|
||||
- name: finish
|
||||
in: path
|
||||
description: internal id of schedule
|
||||
required: true
|
||||
schema:
|
||||
type: boolean
|
||||
example: True
|
||||
responses:
|
||||
200:
|
||||
description: No permission
|
||||
content:
|
||||
'application/json':
|
||||
schema:
|
||||
type: object
|
||||
$ref: "#/components/schemas/TaskScheduleStopResponse"
|
||||
403:
|
||||
description: No permission
|
||||
content:
|
||||
'application/json':
|
||||
schema:
|
||||
type: object
|
||||
$ref: "#/components/schemas/SimpleStatusResponse"
|
||||
404:
|
||||
description: Schedule does not exist
|
||||
content:
|
||||
'application/json':
|
||||
schema:
|
||||
type: object
|
||||
$ref: "#/components/schemas/SimpleStatusResponse"
|
||||
400:
|
||||
description: Operation not valid
|
||||
content:
|
||||
'application/json':
|
||||
schema:
|
||||
type: object
|
||||
$ref: "#/components/schemas/SimpleStatusResponse"
|
||||
/schedules/status/today:
|
||||
get:
|
||||
security:
|
||||
- API_TOKEN: []
|
||||
tags:
|
||||
- schedule
|
||||
description: get number of worked minutes today
|
||||
summary: get number of active minutes
|
||||
responses:
|
||||
200:
|
||||
description: operation successfull
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/ScheduleStatus'
|
||||
404:
|
||||
description: User not found
|
||||
content:
|
||||
'application/json':
|
||||
schema:
|
||||
type: object
|
||||
$ref: "#/components/schemas/SimpleStatusResponse"
|
||||
|
||||
|
||||
|
||||
|
||||
components:
|
||||
@ -1834,3 +2038,106 @@ components:
|
||||
type: string
|
||||
description: name of task
|
||||
example: "Vorlesung zusammenfassen"
|
||||
ScheduleActivateInfo:
|
||||
required:
|
||||
- startTime
|
||||
additionalProperties: false
|
||||
properties:
|
||||
startTime:
|
||||
type: string
|
||||
format: date-time
|
||||
description: point in time at which the schedule was started
|
||||
TaskScheduleStopResponse:
|
||||
required:
|
||||
- workTime
|
||||
additionalProperties: false
|
||||
properties:
|
||||
workTime:
|
||||
type: number
|
||||
description: time where the schedule was active
|
||||
example: 10
|
||||
RecursiveTaskgroupInfo:
|
||||
required:
|
||||
- taskgroupID
|
||||
- taskgroupName
|
||||
- childTaskgroups
|
||||
- activeTasks
|
||||
- hasOverdueTask
|
||||
- amountActiveTasks
|
||||
additionalProperties: false
|
||||
properties:
|
||||
taskgroupID:
|
||||
type: number
|
||||
description: internal id of taskgroup
|
||||
example: 1
|
||||
taskgroupName:
|
||||
type: string
|
||||
description: name of taskgroup
|
||||
example: Taskgroup 1
|
||||
maxLength: 255
|
||||
minLength: 1
|
||||
childTaskgroups:
|
||||
type: array
|
||||
items:
|
||||
$ref: '#/components/schemas/RecursiveTaskgroupInfo'
|
||||
activeTasks:
|
||||
type: array
|
||||
items:
|
||||
$ref: '#/components/schemas/TaskOverviewInfo'
|
||||
hasOverdueTask:
|
||||
type: boolean
|
||||
example: true
|
||||
description: determines whether the taskgroup has an overdue task or not
|
||||
amountActiveTasks:
|
||||
type: number
|
||||
example: 2
|
||||
description: determines the number of active tasks that can be scheduled
|
||||
TaskOverviewInfo:
|
||||
required:
|
||||
- taskID
|
||||
- taskName
|
||||
- activeMinutes
|
||||
- eta
|
||||
- limit
|
||||
- overdue
|
||||
additionalProperties: false
|
||||
properties:
|
||||
taskID:
|
||||
type: number
|
||||
description: internal id of task
|
||||
example: 1
|
||||
taskName:
|
||||
type: string
|
||||
description: name of task
|
||||
example: Vorlesung schauen
|
||||
eta:
|
||||
type: number
|
||||
description: expected time to finish task
|
||||
example: 10
|
||||
minimum: 0
|
||||
limit:
|
||||
type: string
|
||||
format: date
|
||||
description: date until the task has to be finished
|
||||
overdue:
|
||||
type: boolean
|
||||
description: determines whether the task is overdue
|
||||
example: True
|
||||
activeTime:
|
||||
type: number
|
||||
description: number in minutes that was already worked on this task
|
||||
example: 10
|
||||
ScheduleStatus:
|
||||
required:
|
||||
- activeMinutes
|
||||
- missedSchedules
|
||||
additionalProperties: false
|
||||
properties:
|
||||
activeMinutes:
|
||||
type: number
|
||||
example: 1
|
||||
description: number of minutes it was worked today
|
||||
missedSchedules:
|
||||
type: boolean
|
||||
description: states whether a schedule was missed or not
|
||||
example: true
|
Loading…
Reference in New Issue
Block a user