issue-77 #105
@ -41,7 +41,7 @@ public class ScheduleController {
|
|||||||
@GetMapping("/schedules/{taskID}")
|
@GetMapping("/schedules/{taskID}")
|
||||||
public ResponseEntity<?> loadAllSchedulesOfTask(@PathVariable long taskID) {
|
public ResponseEntity<?> loadAllSchedulesOfTask(@PathVariable long taskID) {
|
||||||
PermissionResult<Task> permissionResult = taskService.getTaskPermissions(taskID, SecurityContextHolder.getContext().getAuthentication().getName());
|
PermissionResult<Task> permissionResult = taskService.getTaskPermissions(taskID, SecurityContextHolder.getContext().getAuthentication().getName());
|
||||||
if(!permissionResult.isHasPermissions()) {
|
if(permissionResult.isNoPermissions()) {
|
||||||
return ResponseEntity.status(403).body(new SimpleStatusResponse("failed"));
|
return ResponseEntity.status(403).body(new SimpleStatusResponse("failed"));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -72,7 +72,7 @@ public class ScheduleController {
|
|||||||
|
|
||||||
private ResponseEntity<?> createAbstractSchedule(long taskID, ScheduleFieldInfo scheduleFieldInfo) {
|
private ResponseEntity<?> createAbstractSchedule(long taskID, ScheduleFieldInfo scheduleFieldInfo) {
|
||||||
PermissionResult<Task> permissionResult = taskService.getTaskPermissions(taskID, SecurityContextHolder.getContext().getAuthentication().getName());
|
PermissionResult<Task> permissionResult = taskService.getTaskPermissions(taskID, SecurityContextHolder.getContext().getAuthentication().getName());
|
||||||
if(!permissionResult.isHasPermissions()) {
|
if(permissionResult.isNoPermissions()) {
|
||||||
return ResponseEntity.status(403).body(new SimpleStatusResponse("failed"));
|
return ResponseEntity.status(403).body(new SimpleStatusResponse("failed"));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -111,7 +111,7 @@ public class ScheduleController {
|
|||||||
|
|
||||||
private ResponseEntity<?> editAbstractSchedule(long scheduleID, ScheduleFieldInfo scheduleFieldInfo) {
|
private ResponseEntity<?> editAbstractSchedule(long scheduleID, ScheduleFieldInfo scheduleFieldInfo) {
|
||||||
PermissionResult<AbstractSchedule> permissionResult = taskScheduleService.getSchedulePermissions(scheduleID, SecurityContextHolder.getContext().getAuthentication().getName());
|
PermissionResult<AbstractSchedule> permissionResult = taskScheduleService.getSchedulePermissions(scheduleID, SecurityContextHolder.getContext().getAuthentication().getName());
|
||||||
if(!permissionResult.isHasPermissions()) {
|
if(permissionResult.isNoPermissions()) {
|
||||||
return ResponseEntity.status(403).body(new SimpleStatusResponse("failed"));
|
return ResponseEntity.status(403).body(new SimpleStatusResponse("failed"));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -141,7 +141,7 @@ public class ScheduleController {
|
|||||||
@DeleteMapping("/schedules/{scheduleID}")
|
@DeleteMapping("/schedules/{scheduleID}")
|
||||||
public ResponseEntity<?> deleteSchedule(@PathVariable long scheduleID) {
|
public ResponseEntity<?> deleteSchedule(@PathVariable long scheduleID) {
|
||||||
PermissionResult<AbstractSchedule> permissionResult = taskScheduleService.getSchedulePermissions(scheduleID, SecurityContextHolder.getContext().getAuthentication().getName());
|
PermissionResult<AbstractSchedule> permissionResult = taskScheduleService.getSchedulePermissions(scheduleID, SecurityContextHolder.getContext().getAuthentication().getName());
|
||||||
if(!permissionResult.isHasPermissions()) {
|
if(permissionResult.isNoPermissions()) {
|
||||||
return ResponseEntity.status(403).body(new SimpleStatusResponse("failed"));
|
return ResponseEntity.status(403).body(new SimpleStatusResponse("failed"));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -163,7 +163,7 @@ public class ScheduleController {
|
|||||||
@PostMapping("/schedules/{taskID}/now")
|
@PostMapping("/schedules/{taskID}/now")
|
||||||
public ResponseEntity<?> scheduleNow(@PathVariable long taskID) {
|
public ResponseEntity<?> scheduleNow(@PathVariable long taskID) {
|
||||||
PermissionResult<Task> permissionResult = taskService.getTaskPermissions(taskID, SecurityContextHolder.getContext().getAuthentication().getName());
|
PermissionResult<Task> permissionResult = taskService.getTaskPermissions(taskID, SecurityContextHolder.getContext().getAuthentication().getName());
|
||||||
if(!permissionResult.isHasPermissions()) {
|
if(permissionResult.isNoPermissions()) {
|
||||||
return ResponseEntity.status(403).body(new SimpleStatusResponse("failed"));
|
return ResponseEntity.status(403).body(new SimpleStatusResponse("failed"));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -193,7 +193,7 @@ public class ScheduleController {
|
|||||||
@PostMapping("/schedules/{scheduleID}/activate")
|
@PostMapping("/schedules/{scheduleID}/activate")
|
||||||
public ResponseEntity<?> activateSchedule(@PathVariable long scheduleID) {
|
public ResponseEntity<?> activateSchedule(@PathVariable long scheduleID) {
|
||||||
PermissionResult<AbstractSchedule> permissionResult = taskScheduleService.getSchedulePermissions(scheduleID, SecurityContextHolder.getContext().getAuthentication().getName());
|
PermissionResult<AbstractSchedule> permissionResult = taskScheduleService.getSchedulePermissions(scheduleID, SecurityContextHolder.getContext().getAuthentication().getName());
|
||||||
if(!permissionResult.isHasPermissions()) {
|
if(permissionResult.isNoPermissions()) {
|
||||||
return ResponseEntity.status(403).body(new SimpleStatusResponse("failed"));
|
return ResponseEntity.status(403).body(new SimpleStatusResponse("failed"));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -217,7 +217,7 @@ public class ScheduleController {
|
|||||||
@PostMapping("/schedules/{scheduleID}/stop/{finish}")
|
@PostMapping("/schedules/{scheduleID}/stop/{finish}")
|
||||||
public ResponseEntity<?> stopSchedule(@PathVariable long scheduleID, @PathVariable boolean finish) {
|
public ResponseEntity<?> stopSchedule(@PathVariable long scheduleID, @PathVariable boolean finish) {
|
||||||
PermissionResult<AbstractSchedule> permissionResult = taskScheduleService.getSchedulePermissions(scheduleID, SecurityContextHolder.getContext().getAuthentication().getName());
|
PermissionResult<AbstractSchedule> permissionResult = taskScheduleService.getSchedulePermissions(scheduleID, SecurityContextHolder.getContext().getAuthentication().getName());
|
||||||
if(!permissionResult.isHasPermissions()) {
|
if(permissionResult.isNoPermissions()) {
|
||||||
return ResponseEntity.status(403).body(new SimpleStatusResponse("failed"));
|
return ResponseEntity.status(403).body(new SimpleStatusResponse("failed"));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -232,7 +232,7 @@ public class ScheduleController {
|
|||||||
@PostMapping("/schedules/{taskID}/forgotten")
|
@PostMapping("/schedules/{taskID}/forgotten")
|
||||||
public ResponseEntity<?> registerForgottenSchedule(@PathVariable long taskID, @RequestBody @Valid ForgottenScheduleInfo forgottenScheduleInfo) {
|
public ResponseEntity<?> registerForgottenSchedule(@PathVariable long taskID, @RequestBody @Valid ForgottenScheduleInfo forgottenScheduleInfo) {
|
||||||
PermissionResult<Task> permissionResult = taskService.getTaskPermissions(taskID, SecurityContextHolder.getContext().getAuthentication().getName());
|
PermissionResult<Task> permissionResult = taskService.getTaskPermissions(taskID, SecurityContextHolder.getContext().getAuthentication().getName());
|
||||||
if(!permissionResult.isHasPermissions()) {
|
if(permissionResult.isNoPermissions()) {
|
||||||
return ResponseEntity.status(403).body(new SimpleStatusResponse("failed"));
|
return ResponseEntity.status(403).body(new SimpleStatusResponse("failed"));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -259,7 +259,7 @@ public class ScheduleController {
|
|||||||
List<PermissionResult<AbstractSchedule>> permissionResults = new ArrayList<>();
|
List<PermissionResult<AbstractSchedule>> permissionResults = new ArrayList<>();
|
||||||
for(long scheduleID: scheduleIDs) {
|
for(long scheduleID: scheduleIDs) {
|
||||||
PermissionResult<AbstractSchedule> permissionResult = taskScheduleService.getSchedulePermissions(scheduleID, SecurityContextHolder.getContext().getAuthentication().getName());
|
PermissionResult<AbstractSchedule> permissionResult = taskScheduleService.getSchedulePermissions(scheduleID, SecurityContextHolder.getContext().getAuthentication().getName());
|
||||||
if(!permissionResult.isHasPermissions()) {
|
if(permissionResult.isNoPermissions()) {
|
||||||
return ResponseEntity.status(403).body(new SimpleStatusResponse("failed"));
|
return ResponseEntity.status(403).body(new SimpleStatusResponse("failed"));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -278,7 +278,7 @@ public class ScheduleController {
|
|||||||
@GetMapping("/schedules/{scheduleID}/details")
|
@GetMapping("/schedules/{scheduleID}/details")
|
||||||
public ResponseEntity<?> loadScheduleDetails(@PathVariable long scheduleID) {
|
public ResponseEntity<?> loadScheduleDetails(@PathVariable long scheduleID) {
|
||||||
PermissionResult<AbstractSchedule> permissionResult = taskScheduleService.getSchedulePermissions(scheduleID, SecurityContextHolder.getContext().getAuthentication().getName());
|
PermissionResult<AbstractSchedule> permissionResult = taskScheduleService.getSchedulePermissions(scheduleID, SecurityContextHolder.getContext().getAuthentication().getName());
|
||||||
if(!permissionResult.isHasPermissions()) {
|
if(permissionResult.isNoPermissions()) {
|
||||||
return ResponseEntity.status(403).body(new SimpleStatusResponse("failed"));
|
return ResponseEntity.status(403).body(new SimpleStatusResponse("failed"));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -292,7 +292,7 @@ public class ScheduleController {
|
|||||||
@PostMapping("/schedules/{scheduleID}/stopManual")
|
@PostMapping("/schedules/{scheduleID}/stopManual")
|
||||||
public ResponseEntity<?> stopManual(@PathVariable long scheduleID, @Valid @RequestBody ManualScheduleStopInfo manualScheduleStopInfo) {
|
public ResponseEntity<?> stopManual(@PathVariable long scheduleID, @Valid @RequestBody ManualScheduleStopInfo manualScheduleStopInfo) {
|
||||||
PermissionResult<AbstractSchedule> permissionResult = taskScheduleService.getSchedulePermissions(scheduleID, SecurityContextHolder.getContext().getAuthentication().getName());
|
PermissionResult<AbstractSchedule> permissionResult = taskScheduleService.getSchedulePermissions(scheduleID, SecurityContextHolder.getContext().getAuthentication().getName());
|
||||||
if(!permissionResult.isHasPermissions()) {
|
if(permissionResult.isNoPermissions()) {
|
||||||
return ResponseEntity.status(403).body(new SimpleStatusResponse("failed"));
|
return ResponseEntity.status(403).body(new SimpleStatusResponse("failed"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3,9 +3,7 @@ package core.api.controller;
|
|||||||
import core.api.models.auth.SimpleStatusResponse;
|
import core.api.models.auth.SimpleStatusResponse;
|
||||||
import core.api.models.timemanager.history.TaskgroupActivityInfo;
|
import core.api.models.timemanager.history.TaskgroupActivityInfo;
|
||||||
import core.api.models.timemanager.history.WorkingStatus;
|
import core.api.models.timemanager.history.WorkingStatus;
|
||||||
import core.api.models.timemanager.taskgroup.TaskgroupEntityInfo;
|
|
||||||
import core.entities.timemanager.AbstractSchedule;
|
import core.entities.timemanager.AbstractSchedule;
|
||||||
import core.entities.timemanager.Task;
|
|
||||||
import core.entities.timemanager.Taskgroup;
|
import core.entities.timemanager.Taskgroup;
|
||||||
import core.services.PermissionResult;
|
import core.services.PermissionResult;
|
||||||
import core.services.ServiceExitCode;
|
import core.services.ServiceExitCode;
|
||||||
@ -14,12 +12,10 @@ import core.services.TaskgroupService;
|
|||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.http.ResponseEntity;
|
import org.springframework.http.ResponseEntity;
|
||||||
import org.springframework.security.core.context.SecurityContextHolder;
|
import org.springframework.security.core.context.SecurityContextHolder;
|
||||||
import org.springframework.security.core.parameters.P;
|
|
||||||
import org.springframework.web.bind.annotation.*;
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
|
||||||
import java.time.*;
|
import java.time.*;
|
||||||
import java.time.format.DateTimeFormatter;
|
import java.time.format.DateTimeFormatter;
|
||||||
import java.time.temporal.TemporalAdjusters;
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
|
||||||
@CrossOrigin(origins = "*", maxAge = 3600)
|
@CrossOrigin(origins = "*", maxAge = 3600)
|
||||||
@ -49,7 +45,7 @@ public class StatisticController {
|
|||||||
@GetMapping("/statistics/taskgroup-activity/{taskgroupID}/{startingDate}/{endingDate}/{includeSubTaskgroups}")
|
@GetMapping("/statistics/taskgroup-activity/{taskgroupID}/{startingDate}/{endingDate}/{includeSubTaskgroups}")
|
||||||
public ResponseEntity<?> getTaskgroupActivity(@PathVariable long taskgroupID, @PathVariable String startingDate, @PathVariable String endingDate, @PathVariable boolean includeSubTaskgroups){
|
public ResponseEntity<?> getTaskgroupActivity(@PathVariable long taskgroupID, @PathVariable String startingDate, @PathVariable String endingDate, @PathVariable boolean includeSubTaskgroups){
|
||||||
PermissionResult<Taskgroup> taskgroupPermissionResult = taskgroupService.getTaskgroupByIDAndUsername(taskgroupID, SecurityContextHolder.getContext().getAuthentication().getName());
|
PermissionResult<Taskgroup> taskgroupPermissionResult = taskgroupService.getTaskgroupByIDAndUsername(taskgroupID, SecurityContextHolder.getContext().getAuthentication().getName());
|
||||||
if(!taskgroupPermissionResult.isHasPermissions()) {
|
if(taskgroupPermissionResult.isNoPermissions()) {
|
||||||
return ResponseEntity.status(403).body(new SimpleStatusResponse("failed"));
|
return ResponseEntity.status(403).body(new SimpleStatusResponse("failed"));
|
||||||
} else if(taskgroupPermissionResult.getExitCode() == ServiceExitCode.MISSING_ENTITY) {
|
} else if(taskgroupPermissionResult.getExitCode() == ServiceExitCode.MISSING_ENTITY) {
|
||||||
return ResponseEntity.status(404).body(new SimpleStatusResponse("failed"));
|
return ResponseEntity.status(404).body(new SimpleStatusResponse("failed"));
|
||||||
|
@ -64,7 +64,7 @@ public class TaskController {
|
|||||||
@GetMapping("/tasks/{taskgroupID}/{status}")
|
@GetMapping("/tasks/{taskgroupID}/{status}")
|
||||||
public ResponseEntity<?> listTasksOfTaskgroup(@PathVariable long taskgroupID, @PathVariable String status) {
|
public ResponseEntity<?> listTasksOfTaskgroup(@PathVariable long taskgroupID, @PathVariable String status) {
|
||||||
PermissionResult<Taskgroup> taskgroupPermissionResult = taskgroupService.getTaskgroupByIDAndUsername(taskgroupID, SecurityContextHolder.getContext().getAuthentication().getName());
|
PermissionResult<Taskgroup> taskgroupPermissionResult = taskgroupService.getTaskgroupByIDAndUsername(taskgroupID, SecurityContextHolder.getContext().getAuthentication().getName());
|
||||||
if(!taskgroupPermissionResult.isHasPermissions()) {
|
if(taskgroupPermissionResult.isNoPermissions()) {
|
||||||
return ResponseEntity.status(403).body(new SimpleStatusResponse("failed"));
|
return ResponseEntity.status(403).body(new SimpleStatusResponse("failed"));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -78,7 +78,7 @@ public class TaskController {
|
|||||||
@PutMapping("/tasks/{taskgroupID}")
|
@PutMapping("/tasks/{taskgroupID}")
|
||||||
public ResponseEntity<?> createTask(@PathVariable long taskgroupID, @RequestBody @Valid TaskFieldInfo taskFieldInfo) {
|
public ResponseEntity<?> createTask(@PathVariable long taskgroupID, @RequestBody @Valid TaskFieldInfo taskFieldInfo) {
|
||||||
PermissionResult<Taskgroup> taskgroupPermissionResult = taskgroupService.getTaskgroupByIDAndUsername(taskgroupID, SecurityContextHolder.getContext().getAuthentication().getName());
|
PermissionResult<Taskgroup> taskgroupPermissionResult = taskgroupService.getTaskgroupByIDAndUsername(taskgroupID, SecurityContextHolder.getContext().getAuthentication().getName());
|
||||||
if(!taskgroupPermissionResult.isHasPermissions()) {
|
if(taskgroupPermissionResult.isNoPermissions()) {
|
||||||
return ResponseEntity.status(403).body(new SimpleStatusResponse("failed"));
|
return ResponseEntity.status(403).body(new SimpleStatusResponse("failed"));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -101,7 +101,7 @@ public class TaskController {
|
|||||||
@PostMapping("/tasks/{taskID}")
|
@PostMapping("/tasks/{taskID}")
|
||||||
public ResponseEntity<?> editTask(@PathVariable long taskID, @RequestBody @Valid TaskFieldInfo taskFieldInfo) {
|
public ResponseEntity<?> editTask(@PathVariable long taskID, @RequestBody @Valid TaskFieldInfo taskFieldInfo) {
|
||||||
PermissionResult<Task> taskPermissionResult = taskService.getTaskPermissions(taskID, SecurityContextHolder.getContext().getAuthentication().getName());
|
PermissionResult<Task> taskPermissionResult = taskService.getTaskPermissions(taskID, SecurityContextHolder.getContext().getAuthentication().getName());
|
||||||
if (!taskPermissionResult.isHasPermissions()) {
|
if (taskPermissionResult.isNoPermissions()) {
|
||||||
return ResponseEntity.status(403).body(new SimpleStatusResponse("failed"));
|
return ResponseEntity.status(403).body(new SimpleStatusResponse("failed"));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -124,7 +124,7 @@ public class TaskController {
|
|||||||
@DeleteMapping("/tasks/{taskID}")
|
@DeleteMapping("/tasks/{taskID}")
|
||||||
public ResponseEntity<?> deleteTask(@PathVariable long taskID) {
|
public ResponseEntity<?> deleteTask(@PathVariable long taskID) {
|
||||||
PermissionResult<Task> taskPermissionResult = taskService.getTaskPermissions(taskID, SecurityContextHolder.getContext().getAuthentication().getName());
|
PermissionResult<Task> taskPermissionResult = taskService.getTaskPermissions(taskID, SecurityContextHolder.getContext().getAuthentication().getName());
|
||||||
if (!taskPermissionResult.isHasPermissions()) {
|
if (taskPermissionResult.isNoPermissions()) {
|
||||||
return ResponseEntity.status(403).body(new SimpleStatusResponse("failed"));
|
return ResponseEntity.status(403).body(new SimpleStatusResponse("failed"));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -139,7 +139,7 @@ public class TaskController {
|
|||||||
@GetMapping("/tasks/{taskID}")
|
@GetMapping("/tasks/{taskID}")
|
||||||
public ResponseEntity<?> loadTaskDetails(@PathVariable long taskID) {
|
public ResponseEntity<?> loadTaskDetails(@PathVariable long taskID) {
|
||||||
PermissionResult<Task> taskPermissionResult = taskService.getTaskPermissions(taskID, SecurityContextHolder.getContext().getAuthentication().getName());
|
PermissionResult<Task> taskPermissionResult = taskService.getTaskPermissions(taskID, SecurityContextHolder.getContext().getAuthentication().getName());
|
||||||
if (!taskPermissionResult.isHasPermissions()) {
|
if (taskPermissionResult.isNoPermissions()) {
|
||||||
return ResponseEntity.status(403).body(new SimpleStatusResponse("failed"));
|
return ResponseEntity.status(403).body(new SimpleStatusResponse("failed"));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -153,7 +153,7 @@ public class TaskController {
|
|||||||
@PostMapping("/tasks/{taskID}/finish")
|
@PostMapping("/tasks/{taskID}/finish")
|
||||||
public ResponseEntity<?> finishTask(@PathVariable long taskID) {
|
public ResponseEntity<?> finishTask(@PathVariable long taskID) {
|
||||||
PermissionResult<Task> taskPermissionResult = taskService.getTaskPermissions(taskID, SecurityContextHolder.getContext().getAuthentication().getName());
|
PermissionResult<Task> taskPermissionResult = taskService.getTaskPermissions(taskID, SecurityContextHolder.getContext().getAuthentication().getName());
|
||||||
if (!taskPermissionResult.isHasPermissions()) {
|
if (taskPermissionResult.isNoPermissions()) {
|
||||||
return ResponseEntity.status(403).body(new SimpleStatusResponse("failed"));
|
return ResponseEntity.status(403).body(new SimpleStatusResponse("failed"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -0,0 +1,40 @@
|
|||||||
|
package core.api.controller;
|
||||||
|
|
||||||
|
import core.api.models.timemanager.tasks.repeatinginfo.TaskRepeatDayInfo;
|
||||||
|
import core.api.models.timemanager.tasks.repeatinginfo.TaskRepeatWeekInfo;
|
||||||
|
import core.services.ServiceExitCode;
|
||||||
|
import core.services.ServiceResult;
|
||||||
|
import core.services.TaskSeriesService;
|
||||||
|
import core.services.TaskService;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.http.ResponseEntity;
|
||||||
|
import org.springframework.security.core.context.SecurityContextHolder;
|
||||||
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
|
||||||
|
import javax.validation.Valid;
|
||||||
|
|
||||||
|
@CrossOrigin(origins = "*", maxAge = 3600)
|
||||||
|
@RestController
|
||||||
|
@RequestMapping("/api")
|
||||||
|
public class TaskSeriesController {
|
||||||
|
|
||||||
|
@Autowired private TaskService taskService;
|
||||||
|
@Autowired private TaskSeriesService taskSeriesService;
|
||||||
|
|
||||||
|
@PostMapping("/tasks/taskseries/weekly")
|
||||||
|
public ResponseEntity<?> onCreateTaskSeries(@Valid @RequestBody TaskRepeatWeekInfo taskRepeatWeekInfo) {
|
||||||
|
ServiceExitCode serviceExitCode = taskSeriesService.createTaskSeries(taskRepeatWeekInfo);
|
||||||
|
return serviceExitCode.mapToResponseEntity();
|
||||||
|
}
|
||||||
|
|
||||||
|
@PostMapping("/tasks/{taskID}/taskseries/daily")
|
||||||
|
public ResponseEntity<?> onCreateTaskSeries(@PathVariable long taskID, @Valid @RequestBody TaskRepeatDayInfo taskRepeatDayInfo) {
|
||||||
|
var taskPermission = taskService.getTaskPermissions(taskID, SecurityContextHolder.getContext().getAuthentication().getName());
|
||||||
|
if(taskPermission.hasIssue()) {
|
||||||
|
return taskPermission.mapToResponseEntity();
|
||||||
|
} else {
|
||||||
|
ServiceExitCode serviceExitCode = taskSeriesService.createTaskSeries(taskPermission.getResult(), taskRepeatDayInfo);
|
||||||
|
return serviceExitCode.mapToResponseEntity();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -11,7 +11,6 @@ import org.springframework.web.bind.annotation.*;
|
|||||||
|
|
||||||
import javax.validation.Valid;
|
import javax.validation.Valid;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
@CrossOrigin(origins = "*", maxAge = 3600)
|
@CrossOrigin(origins = "*", maxAge = 3600)
|
||||||
@RestController
|
@RestController
|
||||||
@ -40,7 +39,7 @@ public class TaskgroupController {
|
|||||||
@PostMapping("/taskgroups/{taskgroupID}")
|
@PostMapping("/taskgroups/{taskgroupID}")
|
||||||
public ResponseEntity<?> editTaskgroup(@PathVariable long taskgroupID, @Valid @RequestBody TaskgroupFieldInfo taskgroupFieldInfo) {
|
public ResponseEntity<?> editTaskgroup(@PathVariable long taskgroupID, @Valid @RequestBody TaskgroupFieldInfo taskgroupFieldInfo) {
|
||||||
PermissionResult<Taskgroup> taskgroupPermissionResult = taskgroupService.getTaskgroupByIDAndUsername(taskgroupID, SecurityContextHolder.getContext().getAuthentication().getName());
|
PermissionResult<Taskgroup> taskgroupPermissionResult = taskgroupService.getTaskgroupByIDAndUsername(taskgroupID, SecurityContextHolder.getContext().getAuthentication().getName());
|
||||||
if(!taskgroupPermissionResult.isHasPermissions()) {
|
if(taskgroupPermissionResult.isNoPermissions()) {
|
||||||
return ResponseEntity.status(403).body(new SimpleStatusResponse("failed"));
|
return ResponseEntity.status(403).body(new SimpleStatusResponse("failed"));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -59,7 +58,7 @@ public class TaskgroupController {
|
|||||||
@DeleteMapping("/taskgroups/{taskgroupID}")
|
@DeleteMapping("/taskgroups/{taskgroupID}")
|
||||||
public ResponseEntity<?> deleteTaskgroup(@PathVariable long taskgroupID) {
|
public ResponseEntity<?> deleteTaskgroup(@PathVariable long taskgroupID) {
|
||||||
PermissionResult<Taskgroup> taskgroupPermissionResult = taskgroupService.getTaskgroupByIDAndUsername(taskgroupID, SecurityContextHolder.getContext().getAuthentication().getName());
|
PermissionResult<Taskgroup> taskgroupPermissionResult = taskgroupService.getTaskgroupByIDAndUsername(taskgroupID, SecurityContextHolder.getContext().getAuthentication().getName());
|
||||||
if (!taskgroupPermissionResult.isHasPermissions()) {
|
if (taskgroupPermissionResult.isNoPermissions()) {
|
||||||
return ResponseEntity.status(403).body(new SimpleStatusResponse("failed"));
|
return ResponseEntity.status(403).body(new SimpleStatusResponse("failed"));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -88,7 +87,7 @@ public class TaskgroupController {
|
|||||||
@GetMapping("/taskgroups/{taskgroupID}")
|
@GetMapping("/taskgroups/{taskgroupID}")
|
||||||
public ResponseEntity<?> getDetails(@PathVariable long taskgroupID) {
|
public ResponseEntity<?> getDetails(@PathVariable long taskgroupID) {
|
||||||
PermissionResult<Taskgroup> taskgroupPermissionResult = taskgroupService.getTaskgroupByIDAndUsername(taskgroupID, SecurityContextHolder.getContext().getAuthentication().getName());
|
PermissionResult<Taskgroup> taskgroupPermissionResult = taskgroupService.getTaskgroupByIDAndUsername(taskgroupID, SecurityContextHolder.getContext().getAuthentication().getName());
|
||||||
if(!taskgroupPermissionResult.isHasPermissions()) {
|
if(taskgroupPermissionResult.isNoPermissions()) {
|
||||||
return ResponseEntity.status(403).body(new SimpleStatusResponse("failed"));
|
return ResponseEntity.status(403).body(new SimpleStatusResponse("failed"));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -102,7 +101,7 @@ public class TaskgroupController {
|
|||||||
@DeleteMapping("/taskgroups/{taskgroupID}/clear")
|
@DeleteMapping("/taskgroups/{taskgroupID}/clear")
|
||||||
public ResponseEntity<?> clearTasks(@PathVariable long taskgroupID) {
|
public ResponseEntity<?> clearTasks(@PathVariable long taskgroupID) {
|
||||||
PermissionResult<Taskgroup> taskgroupPermissionResult = taskgroupService.getTaskgroupByIDAndUsername(taskgroupID, SecurityContextHolder.getContext().getAuthentication().getName());
|
PermissionResult<Taskgroup> taskgroupPermissionResult = taskgroupService.getTaskgroupByIDAndUsername(taskgroupID, SecurityContextHolder.getContext().getAuthentication().getName());
|
||||||
if (!taskgroupPermissionResult.isHasPermissions()) {
|
if (taskgroupPermissionResult.isNoPermissions()) {
|
||||||
return ResponseEntity.status(403).body(new SimpleStatusResponse("failed"));
|
return ResponseEntity.status(403).body(new SimpleStatusResponse("failed"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2,6 +2,7 @@ package core.api.models.timemanager.tasks;
|
|||||||
|
|
||||||
import core.api.models.timemanager.taskgroup.TaskgroupEntityInfo;
|
import core.api.models.timemanager.taskgroup.TaskgroupEntityInfo;
|
||||||
import core.entities.timemanager.Task;
|
import core.entities.timemanager.Task;
|
||||||
|
import core.services.TaskSeriesService;
|
||||||
|
|
||||||
import java.time.LocalDate;
|
import java.time.LocalDate;
|
||||||
|
|
||||||
@ -27,10 +28,15 @@ public class TaskEntityInfo {
|
|||||||
private boolean hasActiveSchedules;
|
private boolean hasActiveSchedules;
|
||||||
|
|
||||||
private boolean hasPlannedSchedules;
|
private boolean hasPlannedSchedules;
|
||||||
|
private boolean hasTaskSerie;
|
||||||
|
|
||||||
public TaskEntityInfo(Task task) {
|
public TaskEntityInfo(Task task) {
|
||||||
this.taskID = task.getTaskID();
|
this.taskID = task.getTaskID();
|
||||||
|
if(task.getTaskSerieItem() != null) {
|
||||||
|
this.taskName = TaskSeriesService.insertNameIndex(task.getTaskSerieItem().getSeriesIndex(), task.getTaskName());
|
||||||
|
} else {
|
||||||
this.taskName = task.getTaskName();
|
this.taskName = task.getTaskName();
|
||||||
|
}
|
||||||
this.eta = task.getEta();
|
this.eta = task.getEta();
|
||||||
this.startDate = task.getStartDate();
|
this.startDate = task.getStartDate();
|
||||||
this.deadline = task.getDeadline();
|
this.deadline = task.getDeadline();
|
||||||
@ -42,6 +48,7 @@ public class TaskEntityInfo {
|
|||||||
this.finishable = task.isFinishable();
|
this.finishable = task.isFinishable();
|
||||||
this.hasActiveSchedules = task.hasActiveSchedule();
|
this.hasActiveSchedules = task.hasActiveSchedule();
|
||||||
this.hasPlannedSchedules = task.hasPlannedSchedules();
|
this.hasPlannedSchedules = task.hasPlannedSchedules();
|
||||||
|
this.hasTaskSerie = task.getTaskSerieItem() != null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public long getTaskID() {
|
public long getTaskID() {
|
||||||
@ -131,4 +138,12 @@ public class TaskEntityInfo {
|
|||||||
public void setHasPlannedSchedules(boolean hasPlannedSchedules) {
|
public void setHasPlannedSchedules(boolean hasPlannedSchedules) {
|
||||||
this.hasPlannedSchedules = hasPlannedSchedules;
|
this.hasPlannedSchedules = hasPlannedSchedules;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isHasTaskSerie() {
|
||||||
|
return hasTaskSerie;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setHasTaskSerie(boolean hasTaskSerie) {
|
||||||
|
this.hasTaskSerie = hasTaskSerie;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -3,6 +3,7 @@ package core.api.models.timemanager.tasks;
|
|||||||
import core.api.models.timemanager.taskgroup.TaskgroupEntityInfo;
|
import core.api.models.timemanager.taskgroup.TaskgroupEntityInfo;
|
||||||
import core.entities.timemanager.Task;
|
import core.entities.timemanager.Task;
|
||||||
import core.entities.timemanager.Taskgroup;
|
import core.entities.timemanager.Taskgroup;
|
||||||
|
import core.services.TaskSeriesService;
|
||||||
|
|
||||||
import java.time.LocalDate;
|
import java.time.LocalDate;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@ -20,7 +21,11 @@ public class TaskOverviewInfo {
|
|||||||
|
|
||||||
public TaskOverviewInfo(Task task) {
|
public TaskOverviewInfo(Task task) {
|
||||||
this.taskID = task.getTaskID();
|
this.taskID = task.getTaskID();
|
||||||
|
if(task.getTaskSerieItem() != null) {
|
||||||
|
this.taskName = TaskSeriesService.insertNameIndex(task.getTaskSerieItem().getSeriesIndex(), task.getTaskName());
|
||||||
|
} else {
|
||||||
this.taskName = task.getTaskName();
|
this.taskName = task.getTaskName();
|
||||||
|
}
|
||||||
this.activeMinutes = task.getWorkTime();
|
this.activeMinutes = task.getWorkTime();
|
||||||
this.eta = task.getEta();
|
this.eta = task.getEta();
|
||||||
this.limit = task.getDeadline();
|
this.limit = task.getDeadline();
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
package core.api.models.timemanager.tasks;
|
package core.api.models.timemanager.tasks;
|
||||||
|
|
||||||
import core.entities.timemanager.Task;
|
import core.entities.timemanager.Task;
|
||||||
|
import core.services.TaskSeriesService;
|
||||||
|
|
||||||
public class TaskShortInfo {
|
public class TaskShortInfo {
|
||||||
|
|
||||||
@ -11,7 +12,12 @@ public class TaskShortInfo {
|
|||||||
|
|
||||||
public TaskShortInfo(Task task) {
|
public TaskShortInfo(Task task) {
|
||||||
this.taskID = task.getTaskID();
|
this.taskID = task.getTaskID();
|
||||||
|
if(task.getTaskSerieItem() != null) {
|
||||||
|
this.taskName = TaskSeriesService.insertNameIndex(task.getTaskSerieItem().getSeriesIndex(), task.getTaskName());
|
||||||
|
} else {
|
||||||
this.taskName = task.getTaskName();
|
this.taskName = task.getTaskName();
|
||||||
|
}
|
||||||
|
|
||||||
this.finishable = task.isFinishable();
|
this.finishable = task.isFinishable();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3,6 +3,7 @@ package core.api.models.timemanager.tasks;
|
|||||||
import core.api.models.timemanager.taskgroup.TaskgroupEntityInfo;
|
import core.api.models.timemanager.taskgroup.TaskgroupEntityInfo;
|
||||||
import core.entities.timemanager.Task;
|
import core.entities.timemanager.Task;
|
||||||
import core.entities.timemanager.Taskgroup;
|
import core.entities.timemanager.Taskgroup;
|
||||||
|
import core.services.TaskSeriesService;
|
||||||
|
|
||||||
import java.time.LocalDate;
|
import java.time.LocalDate;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
@ -31,7 +32,11 @@ public class TaskTaskgroupInfo {
|
|||||||
|
|
||||||
public TaskTaskgroupInfo(Task task) {
|
public TaskTaskgroupInfo(Task task) {
|
||||||
this.taskID = task.getTaskID();
|
this.taskID = task.getTaskID();
|
||||||
|
if(task.getTaskSerieItem() != null) {
|
||||||
|
this.taskName = TaskSeriesService.insertNameIndex(task.getTaskSerieItem().getSeriesIndex(), task.getTaskName());
|
||||||
|
} else {
|
||||||
this.taskName = task.getTaskName();
|
this.taskName = task.getTaskName();
|
||||||
|
}
|
||||||
this.eta = task.getEta();
|
this.eta = task.getEta();
|
||||||
this.startDate = task.getStartDate();
|
this.startDate = task.getStartDate();
|
||||||
this.deadline = task.getDeadline();
|
this.deadline = task.getDeadline();
|
||||||
|
@ -0,0 +1,8 @@
|
|||||||
|
package core.api.models.timemanager.tasks.repeatinginfo;
|
||||||
|
|
||||||
|
public enum DeadlineStrategy {
|
||||||
|
|
||||||
|
FIX_DEADLINE,
|
||||||
|
DEADLINE_EQUAL_START,
|
||||||
|
DEADLINE_FIT_START
|
||||||
|
}
|
@ -0,0 +1,38 @@
|
|||||||
|
package core.api.models.timemanager.tasks.repeatinginfo;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||||
|
|
||||||
|
import java.time.LocalDate;
|
||||||
|
|
||||||
|
public class TaskRepeatDayInfo {
|
||||||
|
|
||||||
|
private int offset;
|
||||||
|
private DeadlineStrategy deadlineStrategy;
|
||||||
|
|
||||||
|
@JsonFormat(pattern = "yyyy-MM-dd'T'HH:mm:ss.SSSXXX")
|
||||||
|
private LocalDate endingDate;
|
||||||
|
|
||||||
|
public int getOffset() {
|
||||||
|
return offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setOffset(int offset) {
|
||||||
|
this.offset = offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
public DeadlineStrategy getDeadlineStrategy() {
|
||||||
|
return deadlineStrategy;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDeadlineStrategy(DeadlineStrategy deadlineStrategy) {
|
||||||
|
this.deadlineStrategy = deadlineStrategy;
|
||||||
|
}
|
||||||
|
|
||||||
|
public LocalDate getEndingDate() {
|
||||||
|
return endingDate;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setEndingDate(LocalDate endingDate) {
|
||||||
|
this.endingDate = endingDate;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,27 @@
|
|||||||
|
package core.api.models.timemanager.tasks.repeatinginfo;
|
||||||
|
|
||||||
|
import core.api.models.timemanager.tasks.TaskEntityInfo;
|
||||||
|
import core.entities.timemanager.Task;
|
||||||
|
|
||||||
|
import java.time.DayOfWeek;
|
||||||
|
|
||||||
|
public class TaskRepeatWeekDayInfo {
|
||||||
|
private int offset;
|
||||||
|
private long taskID;
|
||||||
|
|
||||||
|
public int getOffset() {
|
||||||
|
return offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setOffset(int offset) {
|
||||||
|
this.offset = offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
public long getTaskID() {
|
||||||
|
return taskID;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTaskID(long taskID) {
|
||||||
|
this.taskID = taskID;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,41 @@
|
|||||||
|
package core.api.models.timemanager.tasks.repeatinginfo;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||||
|
import org.hibernate.validator.constraints.Length;
|
||||||
|
|
||||||
|
import javax.validation.constraints.Size;
|
||||||
|
import java.time.LocalDate;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class TaskRepeatWeekInfo {
|
||||||
|
|
||||||
|
@Size(min = 1, max = 7)
|
||||||
|
private List<TaskRepeatWeekDayInfo> weekDayInfos;
|
||||||
|
private DeadlineStrategy deadlineStrategy;
|
||||||
|
@JsonFormat(pattern = "yyyy-MM-dd'T'HH:mm:ss.SSSXXX")
|
||||||
|
private LocalDate endDate;
|
||||||
|
|
||||||
|
public List<TaskRepeatWeekDayInfo> getWeekDayInfos() {
|
||||||
|
return weekDayInfos;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setWeekDayInfos(List<TaskRepeatWeekDayInfo> weekDayInfos) {
|
||||||
|
this.weekDayInfos = weekDayInfos;
|
||||||
|
}
|
||||||
|
|
||||||
|
public DeadlineStrategy getDeadlineStrategy() {
|
||||||
|
return deadlineStrategy;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDeadlineStrategy(DeadlineStrategy deadlineStrategy) {
|
||||||
|
this.deadlineStrategy = deadlineStrategy;
|
||||||
|
}
|
||||||
|
|
||||||
|
public LocalDate getEndDate() {
|
||||||
|
return endDate;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setEndDate(LocalDate endDate) {
|
||||||
|
this.endDate = endDate;
|
||||||
|
}
|
||||||
|
}
|
@ -124,4 +124,8 @@ public abstract class AbstractSchedule {
|
|||||||
return (int) duration.toMinutes();
|
return (int) duration.toMinutes();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public abstract AbstractSchedule cloneSchedule();
|
||||||
|
|
||||||
|
public abstract void shiftSchedule(long numberDays);
|
||||||
}
|
}
|
||||||
|
@ -71,4 +71,15 @@ public class AdvancedTaskSchedule extends AbstractSchedule {
|
|||||||
public boolean isMissed(LocalDateTime timeReference) {
|
public boolean isMissed(LocalDateTime timeReference) {
|
||||||
return startTime == null && scheduleEnd.toLocalDate().isBefore(timeReference.toLocalDate());
|
return startTime == null && scheduleEnd.toLocalDate().isBefore(timeReference.toLocalDate());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public AbstractSchedule cloneSchedule() {
|
||||||
|
return new AdvancedTaskSchedule(this.task, this.scheduleStart, this.scheduleEnd);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void shiftSchedule(long numberDays) {
|
||||||
|
this.scheduleStart = this.scheduleStart.plusDays(numberDays);
|
||||||
|
this.scheduleEnd = this.scheduleEnd.plusDays(numberDays);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -52,4 +52,14 @@ public class BasicTaskSchedule extends AbstractSchedule{
|
|||||||
public boolean isMissed(LocalDateTime timeReference) {
|
public boolean isMissed(LocalDateTime timeReference) {
|
||||||
return startTime == null && scheduleDate.isBefore(timeReference.toLocalDate());
|
return startTime == null && scheduleDate.isBefore(timeReference.toLocalDate());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public AbstractSchedule cloneSchedule() {
|
||||||
|
return new BasicTaskSchedule(this.task, this.scheduleDate);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void shiftSchedule(long numberDays) {
|
||||||
|
this.scheduleDate = this.scheduleDate.plusDays(numberDays);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -22,21 +22,16 @@ public class Task {
|
|||||||
@JoinColumn(name = "taskgroup_id")
|
@JoinColumn(name = "taskgroup_id")
|
||||||
private Taskgroup taskgroup;
|
private Taskgroup taskgroup;
|
||||||
private String taskName;
|
private String taskName;
|
||||||
|
|
||||||
private LocalDate startDate;
|
private LocalDate startDate;
|
||||||
|
|
||||||
private LocalDate deadline;
|
private LocalDate deadline;
|
||||||
|
|
||||||
private int eta;
|
private int eta;
|
||||||
|
|
||||||
private boolean finished;
|
private boolean finished;
|
||||||
|
|
||||||
private boolean finishable;
|
private boolean finishable;
|
||||||
|
|
||||||
@OneToMany(mappedBy = "task", cascade = CascadeType.ALL, fetch = FetchType.EAGER, orphanRemoval = true)
|
@OneToMany(mappedBy = "task", cascade = CascadeType.ALL, fetch = FetchType.EAGER, orphanRemoval = true)
|
||||||
private List<AbstractSchedule> basicTaskSchedules;
|
private List<AbstractSchedule> basicTaskSchedules;
|
||||||
|
|
||||||
private int workTime;
|
private int workTime;
|
||||||
|
@OneToOne(mappedBy = "task", cascade = CascadeType.ALL, orphanRemoval = true)
|
||||||
|
private TaskSerieItem taskSerieItem;
|
||||||
|
|
||||||
public Task() {
|
public Task() {
|
||||||
this.basicTaskSchedules = new ArrayList<>();
|
this.basicTaskSchedules = new ArrayList<>();
|
||||||
@ -52,6 +47,17 @@ public class Task {
|
|||||||
this.finishable = taskFieldInfo.isFinishable();
|
this.finishable = taskFieldInfo.isFinishable();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static Task cloneTask(Task task) {
|
||||||
|
Task clonedTask = new Task();
|
||||||
|
clonedTask.setTaskgroup(task.getTaskgroup());
|
||||||
|
clonedTask.setTaskName(task.taskName);
|
||||||
|
clonedTask.setEta(task.eta);
|
||||||
|
clonedTask.setFinished(false);
|
||||||
|
clonedTask.setFinishable(task.finishable);
|
||||||
|
return clonedTask;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
public long getTaskID() {
|
public long getTaskID() {
|
||||||
return taskID;
|
return taskID;
|
||||||
}
|
}
|
||||||
@ -124,6 +130,14 @@ public class Task {
|
|||||||
this.taskID = taskID;
|
this.taskID = taskID;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public TaskSerieItem getTaskSerieItem() {
|
||||||
|
return taskSerieItem;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTaskSerieItem(TaskSerieItem taskSerieItem) {
|
||||||
|
this.taskSerieItem = taskSerieItem;
|
||||||
|
}
|
||||||
|
|
||||||
public List<AbstractSchedule> getBasicTaskSchedules() {
|
public List<AbstractSchedule> getBasicTaskSchedules() {
|
||||||
if(basicTaskSchedules == null) {
|
if(basicTaskSchedules == null) {
|
||||||
return new ArrayList<>();
|
return new ArrayList<>();
|
||||||
@ -140,7 +154,7 @@ public class Task {
|
|||||||
if (this == o) return true;
|
if (this == o) return true;
|
||||||
if (o == null || getClass() != o.getClass()) return false;
|
if (o == null || getClass() != o.getClass()) return false;
|
||||||
Task task = (Task) o;
|
Task task = (Task) o;
|
||||||
return taskID == task.taskID && eta == task.eta && finished == task.finished && workTime == task.workTime && Objects.equals(taskgroup, task.taskgroup) && Objects.equals(taskName, task.taskName) && Objects.equals(startDate, task.startDate) && Objects.equals(deadline, task.deadline);
|
return taskID == task.taskID;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -0,0 +1,42 @@
|
|||||||
|
package core.entities.timemanager;
|
||||||
|
|
||||||
|
import javax.persistence.*;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@Entity
|
||||||
|
@Table(name = "task_series")
|
||||||
|
public class TaskSerie {
|
||||||
|
|
||||||
|
@Id
|
||||||
|
@GeneratedValue(strategy = GenerationType.AUTO)
|
||||||
|
private long taskSerieID;
|
||||||
|
|
||||||
|
@OneToMany(fetch = FetchType.EAGER, mappedBy = "taskSerie", orphanRemoval = true)
|
||||||
|
List<TaskSerieItem> tasks = new ArrayList<>();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public long getTaskSerieID() {
|
||||||
|
return taskSerieID;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTaskSerieID(long taskSerieID) {
|
||||||
|
this.taskSerieID = taskSerieID;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<TaskSerieItem> getTasks() {
|
||||||
|
return tasks;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTasks(List<TaskSerieItem> tasks) {
|
||||||
|
this.tasks = tasks;
|
||||||
|
}
|
||||||
|
|
||||||
|
public TaskSerieItem addTask(Task task) {
|
||||||
|
TaskSerieItem taskSerieItem = new TaskSerieItem(this, task, this.tasks.size()+1);
|
||||||
|
this.tasks.add(taskSerieItem);
|
||||||
|
return taskSerieItem;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,78 @@
|
|||||||
|
package core.entities.timemanager;
|
||||||
|
|
||||||
|
import javax.persistence.*;
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
|
@Entity
|
||||||
|
@Table(name = "task_series_items")
|
||||||
|
public class TaskSerieItem {
|
||||||
|
|
||||||
|
@Id
|
||||||
|
@GeneratedValue(strategy = GenerationType.AUTO)
|
||||||
|
private long itemID;
|
||||||
|
|
||||||
|
@ManyToOne
|
||||||
|
@JoinColumn(referencedColumnName = "taskSerieID")
|
||||||
|
private TaskSerie taskSerie;
|
||||||
|
|
||||||
|
@OneToOne
|
||||||
|
@JoinColumn(name = "task_id")
|
||||||
|
private Task task;
|
||||||
|
|
||||||
|
|
||||||
|
private int seriesIndex;
|
||||||
|
|
||||||
|
public TaskSerieItem(TaskSerie taskSerie, Task task, int index) {
|
||||||
|
this.taskSerie = taskSerie;
|
||||||
|
this.seriesIndex = index;
|
||||||
|
this.task = task;
|
||||||
|
}
|
||||||
|
|
||||||
|
public TaskSerieItem() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public long getItemID() {
|
||||||
|
return itemID;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setItemID(long itemID) {
|
||||||
|
this.itemID = itemID;
|
||||||
|
}
|
||||||
|
|
||||||
|
public TaskSerie getTaskSerie() {
|
||||||
|
return taskSerie;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTaskSerie(TaskSerie taskSerie) {
|
||||||
|
this.taskSerie = taskSerie;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getSeriesIndex() {
|
||||||
|
return seriesIndex;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSeriesIndex(int seriesIndex) {
|
||||||
|
this.seriesIndex = seriesIndex;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Task getTask() {
|
||||||
|
return task;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTask(Task task) {
|
||||||
|
this.task = task;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object o) {
|
||||||
|
if (this == o) return true;
|
||||||
|
if (o == null || getClass() != o.getClass()) return false;
|
||||||
|
TaskSerieItem that = (TaskSerieItem) o;
|
||||||
|
return itemID == that.itemID;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return Objects.hash(itemID);
|
||||||
|
}
|
||||||
|
}
|
@ -20,6 +20,7 @@ public interface TaskRepository extends CrudRepository<Task, Long> {
|
|||||||
|
|
||||||
@Modifying
|
@Modifying
|
||||||
@Transactional
|
@Transactional
|
||||||
|
@Query(value = "DELETE FROM Task t WHERE t.taskgroup = ?1")
|
||||||
void deleteAllByTaskgroup(Taskgroup taskgroup);
|
void deleteAllByTaskgroup(Taskgroup taskgroup);
|
||||||
|
|
||||||
@Transactional
|
@Transactional
|
||||||
|
@ -0,0 +1,19 @@
|
|||||||
|
package core.repositories.timemanager;
|
||||||
|
|
||||||
|
import core.entities.timemanager.TaskSerieItem;
|
||||||
|
import core.entities.timemanager.Taskgroup;
|
||||||
|
import org.springframework.data.jpa.repository.Modifying;
|
||||||
|
import org.springframework.data.jpa.repository.Query;
|
||||||
|
import org.springframework.data.repository.CrudRepository;
|
||||||
|
import org.springframework.stereotype.Repository;
|
||||||
|
|
||||||
|
import javax.transaction.Transactional;
|
||||||
|
|
||||||
|
@Repository
|
||||||
|
public interface TaskSerieItemRepository extends CrudRepository<TaskSerieItem, Long> {
|
||||||
|
|
||||||
|
@Query(value = "DELETE FROM TaskSerieItem tsi WHERE tsi.task IN (SELECT t FROM Task t WHERE t.taskgroup = ?1)")
|
||||||
|
@Modifying
|
||||||
|
@Transactional
|
||||||
|
void deleteByTaskgroup(Taskgroup taskgroup);
|
||||||
|
}
|
@ -0,0 +1,23 @@
|
|||||||
|
package core.repositories.timemanager;
|
||||||
|
|
||||||
|
import core.entities.timemanager.TaskSerie;
|
||||||
|
import core.entities.timemanager.Taskgroup;
|
||||||
|
import org.springframework.data.jpa.repository.Modifying;
|
||||||
|
import org.springframework.data.jpa.repository.Query;
|
||||||
|
import org.springframework.data.repository.CrudRepository;
|
||||||
|
import org.springframework.data.repository.query.Param;
|
||||||
|
import org.springframework.stereotype.Repository;
|
||||||
|
|
||||||
|
import javax.transaction.Transactional;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@Repository
|
||||||
|
public interface TaskSeriesRepository extends CrudRepository<TaskSerie, Long> {
|
||||||
|
@Query("SELECT DISTINCT ts FROM TaskSerie ts JOIN ts.tasks tsi JOIN tsi.task t WHERE t.taskgroup = :taskgroup")
|
||||||
|
List<TaskSerie> findByTaskgroup(@Param("taskgroup")Taskgroup taskgroup);
|
||||||
|
|
||||||
|
@Modifying
|
||||||
|
@Transactional
|
||||||
|
@Query(value = "DELETE FROM TaskSerie ts WHERE ts.tasks.size = 0")
|
||||||
|
void deleteUnreferenced();
|
||||||
|
}
|
@ -1,5 +1,8 @@
|
|||||||
package core.services;
|
package core.services;
|
||||||
|
|
||||||
|
import core.api.models.auth.SimpleStatusResponse;
|
||||||
|
import org.springframework.http.ResponseEntity;
|
||||||
|
|
||||||
public class PermissionResult <T> extends ServiceResult<T> {
|
public class PermissionResult <T> extends ServiceResult<T> {
|
||||||
|
|
||||||
private boolean hasPermissions;
|
private boolean hasPermissions;
|
||||||
@ -30,11 +33,25 @@ public class PermissionResult <T> extends ServiceResult<T> {
|
|||||||
this.hasPermissions = hasPermissions;
|
this.hasPermissions = hasPermissions;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isHasPermissions() {
|
public boolean isNoPermissions() {
|
||||||
return hasPermissions;
|
return !hasPermissions;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setHasPermissions(boolean hasPermissions) {
|
public void setHasPermissions(boolean hasPermissions) {
|
||||||
this.hasPermissions = hasPermissions;
|
this.hasPermissions = hasPermissions;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ResponseEntity<?> mapToResponseEntity() {
|
||||||
|
if(isNoPermissions()) {
|
||||||
|
return ResponseEntity.status(403).body(new SimpleStatusResponse("failed"));
|
||||||
|
} else {
|
||||||
|
return super.mapToResponseEntity();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean hasIssue() {
|
||||||
|
return super.hasIssue() || isNoPermissions();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,8 @@
|
|||||||
package core.services;
|
package core.services;
|
||||||
|
|
||||||
|
import core.api.models.auth.SimpleStatusResponse;
|
||||||
|
import org.springframework.http.ResponseEntity;
|
||||||
|
|
||||||
public enum ServiceExitCode {
|
public enum ServiceExitCode {
|
||||||
|
|
||||||
OK,
|
OK,
|
||||||
@ -7,4 +10,13 @@ public enum ServiceExitCode {
|
|||||||
MISSING_ENTITY,
|
MISSING_ENTITY,
|
||||||
INVALID_OPERATION,
|
INVALID_OPERATION,
|
||||||
INVALID_PARAMETER;
|
INVALID_PARAMETER;
|
||||||
|
|
||||||
|
public ResponseEntity<SimpleStatusResponse> mapToResponseEntity() {
|
||||||
|
return switch (this) {
|
||||||
|
case OK -> ResponseEntity.ok(new SimpleStatusResponse("success"));
|
||||||
|
case MISSING_ENTITY -> ResponseEntity.status(404).body(new SimpleStatusResponse("failed"));
|
||||||
|
case ENTITY_ALREADY_EXIST -> ResponseEntity.status(409).body(new SimpleStatusResponse("failed"));
|
||||||
|
case INVALID_OPERATION, INVALID_PARAMETER -> ResponseEntity.status(400).body(new SimpleStatusResponse("failed"));
|
||||||
|
};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,8 @@
|
|||||||
package core.services;
|
package core.services;
|
||||||
|
|
||||||
|
import core.api.models.auth.SimpleStatusResponse;
|
||||||
|
import org.springframework.http.ResponseEntity;
|
||||||
|
|
||||||
public class ServiceResult <T> {
|
public class ServiceResult <T> {
|
||||||
|
|
||||||
private ServiceExitCode exitCode;
|
private ServiceExitCode exitCode;
|
||||||
@ -34,4 +37,12 @@ public class ServiceResult <T> {
|
|||||||
public void setResult(T result) {
|
public void setResult(T result) {
|
||||||
this.result = result;
|
this.result = result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean hasIssue() {
|
||||||
|
return exitCode != ServiceExitCode.OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ResponseEntity<?> mapToResponseEntity() {
|
||||||
|
return exitCode.mapToResponseEntity();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
184
backend/src/main/java/core/services/TaskSeriesService.java
Normal file
184
backend/src/main/java/core/services/TaskSeriesService.java
Normal file
@ -0,0 +1,184 @@
|
|||||||
|
package core.services;
|
||||||
|
|
||||||
|
import core.api.models.timemanager.tasks.repeatinginfo.DeadlineStrategy;
|
||||||
|
import core.api.models.timemanager.tasks.repeatinginfo.TaskRepeatDayInfo;
|
||||||
|
import core.api.models.timemanager.tasks.repeatinginfo.TaskRepeatWeekDayInfo;
|
||||||
|
import core.api.models.timemanager.tasks.repeatinginfo.TaskRepeatWeekInfo;
|
||||||
|
import core.entities.timemanager.*;
|
||||||
|
import core.repositories.timemanager.ScheduleRepository;
|
||||||
|
import core.repositories.timemanager.TaskRepository;
|
||||||
|
import core.repositories.timemanager.TaskSerieItemRepository;
|
||||||
|
import core.repositories.timemanager.TaskSeriesRepository;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
import java.time.Duration;
|
||||||
|
import java.time.LocalDate;
|
||||||
|
import java.time.temporal.ChronoUnit;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Comparator;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
|
@Service
|
||||||
|
public class TaskSeriesService {
|
||||||
|
|
||||||
|
@Autowired private TaskRepository taskRepository;
|
||||||
|
@Autowired private TaskSeriesRepository taskSeriesRepository;
|
||||||
|
@Autowired private TaskSerieItemRepository taskSerieItemRepository;
|
||||||
|
@Autowired private ScheduleRepository scheduleRepository;
|
||||||
|
|
||||||
|
|
||||||
|
public ServiceExitCode createTaskSeries(TaskRepeatWeekInfo taskRepeatInfo) {
|
||||||
|
List<Task> createdTasks = new ArrayList<>();
|
||||||
|
TaskSerie taskSerie = new TaskSerie();
|
||||||
|
List<AbstractSchedule> abstractSchedules = new ArrayList<>();
|
||||||
|
|
||||||
|
for(TaskRepeatWeekDayInfo taskRepeatDayInfo : taskRepeatInfo.getWeekDayInfos()) {
|
||||||
|
Optional<Task> task = taskRepository.findById(taskRepeatDayInfo.getTaskID());
|
||||||
|
if(task.isEmpty()) return ServiceExitCode.MISSING_ENTITY;
|
||||||
|
|
||||||
|
TaskSerieItem rootItem = taskSerie.addTask(task.get());
|
||||||
|
task.get().setTaskSerieItem(rootItem);
|
||||||
|
|
||||||
|
LocalDate currentTaskDate = task.get().getStartDate().plusDays(taskRepeatDayInfo.getOffset());
|
||||||
|
while(currentTaskDate.isBefore(taskRepeatInfo.getEndDate())) {
|
||||||
|
Task clonedTask = Task.cloneTask(task.get());
|
||||||
|
clonedTask.setStartDate(currentTaskDate);
|
||||||
|
|
||||||
|
TaskSerieItem taskSerieItem = taskSerie.addTask(clonedTask);
|
||||||
|
clonedTask.setTaskSerieItem(taskSerieItem);
|
||||||
|
createdTasks.add(clonedTask);
|
||||||
|
|
||||||
|
abstractSchedules.addAll(cloneSchedules(task.get(), clonedTask));
|
||||||
|
currentTaskDate = currentTaskDate.plusDays(taskRepeatDayInfo.getOffset());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
taskSerie.getTasks().sort(Comparator.comparing(o -> o.getTask().getStartDate()));
|
||||||
|
for(int i=0; i<taskSerie.getTasks().size(); i++) {
|
||||||
|
taskSerie.getTasks().get(i).setSeriesIndex(i+1);
|
||||||
|
if(taskRepeatInfo.getDeadlineStrategy() == DeadlineStrategy.DEADLINE_EQUAL_START) {
|
||||||
|
taskSerie.getTasks().get(i).getTask().setDeadline(taskSerie.getTasks().get(i).getTask().getStartDate());
|
||||||
|
} else {
|
||||||
|
if(i + 1 == taskSerie.getTasks().size()) {
|
||||||
|
int firstWeekDayIndex = i % taskRepeatInfo.getWeekDayInfos().size();
|
||||||
|
LocalDate reference_start = taskSerie.getTasks().get(firstWeekDayIndex).getTask().getStartDate();
|
||||||
|
LocalDate reference_deadline = taskSerie.getTasks().get(firstWeekDayIndex).getTask().getDeadline();
|
||||||
|
|
||||||
|
Duration duration = Duration.between(reference_start, reference_deadline);
|
||||||
|
long days = duration.toDays();
|
||||||
|
taskSerie.getTasks().get(i).getTask().setDeadline(taskSerie.getTasks().get(i).getTask().getStartDate().plusDays(days));
|
||||||
|
} else {
|
||||||
|
taskSerie.getTasks().get(i).getTask().setDeadline(taskSerie.getTasks().get(i+1).getTask().getStartDate().minusDays(1));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
taskSeriesRepository.save(taskSerie);
|
||||||
|
taskRepository.saveAll(createdTasks);
|
||||||
|
taskSerieItemRepository.saveAll(taskSerie.getTasks());
|
||||||
|
scheduleRepository.saveAll(abstractSchedules);
|
||||||
|
|
||||||
|
return ServiceExitCode.OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ServiceExitCode createTaskSeries(Task rootTask, TaskRepeatDayInfo taskRepeatInfo) {
|
||||||
|
if(taskRepeatInfo.getDeadlineStrategy() == DeadlineStrategy.FIX_DEADLINE) {
|
||||||
|
return ServiceExitCode.INVALID_PARAMETER;
|
||||||
|
}
|
||||||
|
|
||||||
|
List<Task> taskList = new ArrayList<>();
|
||||||
|
List<AbstractSchedule> abstractSchedules = new ArrayList<>();
|
||||||
|
TaskSerie taskSerie = new TaskSerie();
|
||||||
|
TaskSerieItem rootItem = taskSerie.addTask(rootTask);
|
||||||
|
rootTask.setTaskSerieItem(rootItem);
|
||||||
|
|
||||||
|
LocalDate currentTaskDate = rootTask.getStartDate().plusDays(taskRepeatInfo.getOffset());
|
||||||
|
while(currentTaskDate.isBefore(taskRepeatInfo.getEndingDate())) {
|
||||||
|
Task task = Task.cloneTask(rootTask);
|
||||||
|
task.setStartDate(currentTaskDate);
|
||||||
|
if(taskRepeatInfo.getDeadlineStrategy() == DeadlineStrategy.DEADLINE_EQUAL_START) {
|
||||||
|
task.setDeadline(currentTaskDate);
|
||||||
|
} else if(taskRepeatInfo.getDeadlineStrategy() == DeadlineStrategy.DEADLINE_FIT_START) {
|
||||||
|
task.setDeadline(currentTaskDate.plusDays(taskRepeatInfo.getOffset()-1));
|
||||||
|
}
|
||||||
|
TaskSerieItem taskSerieItem = taskSerie.addTask(task);
|
||||||
|
taskList.add(task);
|
||||||
|
task.setTaskSerieItem(taskSerieItem);
|
||||||
|
|
||||||
|
abstractSchedules.addAll(cloneSchedules(rootTask, task));
|
||||||
|
currentTaskDate = currentTaskDate.plusDays(taskRepeatInfo.getOffset());
|
||||||
|
}
|
||||||
|
|
||||||
|
taskSeriesRepository.save(taskSerie);
|
||||||
|
taskRepository.saveAll(taskList);
|
||||||
|
taskSerieItemRepository.saveAll(taskSerie.getTasks());
|
||||||
|
scheduleRepository.saveAll(abstractSchedules);
|
||||||
|
|
||||||
|
return ServiceExitCode.OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<AbstractSchedule> cloneSchedules(Task previousTask, Task nextTask) {
|
||||||
|
long numberDays = ChronoUnit.DAYS.between(previousTask.getStartDate(), nextTask.getStartDate());
|
||||||
|
|
||||||
|
List<AbstractSchedule> clonedSchedules = new ArrayList<>();
|
||||||
|
for(AbstractSchedule abstractSchedule : previousTask.getBasicTaskSchedules()) {
|
||||||
|
AbstractSchedule clonedSchedule = abstractSchedule.cloneSchedule();
|
||||||
|
clonedSchedule.shiftSchedule(numberDays);
|
||||||
|
|
||||||
|
clonedSchedules.add(clonedSchedule);
|
||||||
|
}
|
||||||
|
return clonedSchedules;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void deleteTaskSeriesItem(Task task) {
|
||||||
|
TaskSerieItem item = task.getTaskSerieItem();
|
||||||
|
TaskSerie taskSerie = task.getTaskSerieItem().getTaskSerie();
|
||||||
|
taskSerie.getTasks().remove(item);
|
||||||
|
task.setTaskSerieItem(null);
|
||||||
|
taskSerieItemRepository.delete(item);
|
||||||
|
if(taskSerie.getTasks().isEmpty()) {
|
||||||
|
for(TaskSerieItem taskSerieItem : taskSerie.getTasks()) {
|
||||||
|
taskSerieItem.setTaskSerie(null);
|
||||||
|
}
|
||||||
|
taskSerie.getTasks().clear();
|
||||||
|
taskSeriesRepository.delete(taskSerie);
|
||||||
|
} else {
|
||||||
|
repearIndexing(taskSerie);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void repearIndexing(TaskSerie taskSerie) {
|
||||||
|
taskSerie.getTasks().sort(Comparator.comparingInt(TaskSerieItem::getSeriesIndex));
|
||||||
|
List<TaskSerieItem> updatedItems = new ArrayList<>();
|
||||||
|
int currentIndex = 1;
|
||||||
|
for(TaskSerieItem taskSerieItem : taskSerie.getTasks()) {
|
||||||
|
if(taskSerieItem.getSeriesIndex() != currentIndex) {
|
||||||
|
taskSerieItem.setSeriesIndex(currentIndex);
|
||||||
|
updatedItems.add(taskSerieItem);
|
||||||
|
}
|
||||||
|
|
||||||
|
currentIndex++;
|
||||||
|
}
|
||||||
|
|
||||||
|
taskSerieItemRepository.saveAll(updatedItems);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void deleteTaskSerieByTaskgroup(Taskgroup taskgroup) {
|
||||||
|
taskSerieItemRepository.deleteByTaskgroup(taskgroup);
|
||||||
|
taskSeriesRepository.deleteUnreferenced();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String convertIndexToString(int index) {
|
||||||
|
if(index < 10) {
|
||||||
|
return "0" + index;
|
||||||
|
} else {
|
||||||
|
return String.valueOf(index);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String insertNameIndex(int seriesIndex, String taskName) {
|
||||||
|
return taskName.replaceAll("\\$\\{i}", convertIndexToString(seriesIndex));
|
||||||
|
}
|
||||||
|
}
|
@ -6,6 +6,8 @@ import core.entities.timemanager.AbstractSchedule;
|
|||||||
import core.entities.timemanager.Task;
|
import core.entities.timemanager.Task;
|
||||||
import core.entities.timemanager.Taskgroup;
|
import core.entities.timemanager.Taskgroup;
|
||||||
import core.repositories.timemanager.TaskRepository;
|
import core.repositories.timemanager.TaskRepository;
|
||||||
|
import core.repositories.timemanager.TaskSerieItemRepository;
|
||||||
|
import core.repositories.timemanager.TaskSeriesRepository;
|
||||||
import core.repositories.timemanager.TaskgroupRepository;
|
import core.repositories.timemanager.TaskgroupRepository;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
@ -20,20 +22,20 @@ public class TaskService {
|
|||||||
private final TaskScheduleService taskScheduleService;
|
private final TaskScheduleService taskScheduleService;
|
||||||
private final TaskgroupRepository taskgroupRepository;
|
private final TaskgroupRepository taskgroupRepository;
|
||||||
|
|
||||||
|
private final TaskSeriesService taskSeriesService;
|
||||||
|
|
||||||
|
|
||||||
public TaskService(@Autowired TaskRepository taskRepository,
|
public TaskService(@Autowired TaskRepository taskRepository,
|
||||||
@Autowired TaskScheduleService taskScheduleService,
|
@Autowired TaskScheduleService taskScheduleService,
|
||||||
TaskgroupRepository taskgroupRepository) {
|
@Autowired TaskgroupRepository taskgroupRepository,
|
||||||
|
@Autowired TaskSeriesService taskSeriesService) {
|
||||||
this.taskRepository = taskRepository;
|
this.taskRepository = taskRepository;
|
||||||
this.taskScheduleService = taskScheduleService;
|
this.taskScheduleService = taskScheduleService;
|
||||||
this.taskgroupRepository = taskgroupRepository;
|
this.taskgroupRepository = taskgroupRepository;
|
||||||
|
this.taskSeriesService = taskSeriesService;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ServiceResult<Task> createTask(Taskgroup taskgroup, TaskFieldInfo taskFieldInfo) {
|
public ServiceResult<Task> createTask(Taskgroup taskgroup, TaskFieldInfo taskFieldInfo) {
|
||||||
if(existTaskByName(taskgroup.getTasks(), taskFieldInfo.getTaskName())) {
|
|
||||||
return new ServiceResult<>(ServiceExitCode.ENTITY_ALREADY_EXIST);
|
|
||||||
}
|
|
||||||
|
|
||||||
//Check for invalid date (deadline before start
|
//Check for invalid date (deadline before start
|
||||||
if(taskFieldInfo.getStartDate() != null && taskFieldInfo.getDeadline() != null &&
|
if(taskFieldInfo.getStartDate() != null && taskFieldInfo.getDeadline() != null &&
|
||||||
taskFieldInfo.getDeadline().isBefore(taskFieldInfo.getStartDate())) {
|
taskFieldInfo.getDeadline().isBefore(taskFieldInfo.getStartDate())) {
|
||||||
@ -86,16 +88,17 @@ public class TaskService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void deleteTask(Task task) {
|
public void deleteTask(Task task) {
|
||||||
//taskScheduleService.deleteScheduleByTask(task);
|
|
||||||
System.err.println(task.getTaskID());
|
|
||||||
task.getTaskgroup().getTasks().remove(task);
|
task.getTaskgroup().getTasks().remove(task);
|
||||||
taskgroupRepository.save(task.getTaskgroup());
|
taskgroupRepository.save(task.getTaskgroup());
|
||||||
task.setTaskgroup(null);
|
if(task.getTaskSerieItem() != null) {
|
||||||
taskRepository.save(task);
|
taskSeriesService.deleteTaskSeriesItem(task);
|
||||||
|
}
|
||||||
taskRepository.delete(task);
|
taskRepository.delete(task);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void clearTasks(Taskgroup taskgroup) {
|
public void clearTasks(Taskgroup taskgroup) {
|
||||||
|
taskSeriesService.deleteTaskSerieByTaskgroup(taskgroup);
|
||||||
taskRepository.deleteAllByTaskgroup(taskgroup);
|
taskRepository.deleteAllByTaskgroup(taskgroup);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -10,6 +10,7 @@ api/properties.service.ts
|
|||||||
api/schedule.service.ts
|
api/schedule.service.ts
|
||||||
api/task.service.ts
|
api/task.service.ts
|
||||||
api/taskgroup.service.ts
|
api/taskgroup.service.ts
|
||||||
|
api/taskseries.service.ts
|
||||||
api/users.service.ts
|
api/users.service.ts
|
||||||
configuration.ts
|
configuration.ts
|
||||||
encoder.ts
|
encoder.ts
|
||||||
@ -47,6 +48,9 @@ model/simpleStatusResponse.ts
|
|||||||
model/taskEntityInfo.ts
|
model/taskEntityInfo.ts
|
||||||
model/taskFieldInfo.ts
|
model/taskFieldInfo.ts
|
||||||
model/taskOverviewInfo.ts
|
model/taskOverviewInfo.ts
|
||||||
|
model/taskRepeatDayInfo.ts
|
||||||
|
model/taskRepeatWeekDayInfo.ts
|
||||||
|
model/taskRepeatWeekInfo.ts
|
||||||
model/taskScheduleStopResponse.ts
|
model/taskScheduleStopResponse.ts
|
||||||
model/taskShortInfo.ts
|
model/taskShortInfo.ts
|
||||||
model/taskTaskgroupInfo.ts
|
model/taskTaskgroupInfo.ts
|
||||||
|
@ -10,6 +10,7 @@ import { PropertiesService } from './api/properties.service';
|
|||||||
import { ScheduleService } from './api/schedule.service';
|
import { ScheduleService } from './api/schedule.service';
|
||||||
import { TaskService } from './api/task.service';
|
import { TaskService } from './api/task.service';
|
||||||
import { TaskgroupService } from './api/taskgroup.service';
|
import { TaskgroupService } from './api/taskgroup.service';
|
||||||
|
import { TaskseriesService } from './api/taskseries.service';
|
||||||
import { UsersService } from './api/users.service';
|
import { UsersService } from './api/users.service';
|
||||||
|
|
||||||
@NgModule({
|
@NgModule({
|
||||||
|
@ -14,6 +14,8 @@ export * from './task.service';
|
|||||||
import { TaskService } from './task.service';
|
import { TaskService } from './task.service';
|
||||||
export * from './taskgroup.service';
|
export * from './taskgroup.service';
|
||||||
import { TaskgroupService } from './taskgroup.service';
|
import { TaskgroupService } from './taskgroup.service';
|
||||||
|
export * from './taskseries.service';
|
||||||
|
import { TaskseriesService } from './taskseries.service';
|
||||||
export * from './users.service';
|
export * from './users.service';
|
||||||
import { UsersService } from './users.service';
|
import { UsersService } from './users.service';
|
||||||
export const APIS = [AccountService, HistoryService, LoginService, NtfyService, PropertiesService, ScheduleService, TaskService, TaskgroupService, UsersService];
|
export const APIS = [AccountService, HistoryService, LoginService, NtfyService, PropertiesService, ScheduleService, TaskService, TaskgroupService, TaskseriesService, UsersService];
|
||||||
|
226
frontend/src/api/api/taskseries.service.ts
Normal file
226
frontend/src/api/api/taskseries.service.ts
Normal file
@ -0,0 +1,226 @@
|
|||||||
|
/**
|
||||||
|
* 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 { SimpleStatusResponse } from '../model/models';
|
||||||
|
import { TaskRepeatDayInfo } from '../model/models';
|
||||||
|
import { TaskRepeatWeekInfo } from '../model/models';
|
||||||
|
|
||||||
|
import { BASE_PATH, COLLECTION_FORMATS } from '../variables';
|
||||||
|
import { Configuration } from '../configuration';
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@Injectable({
|
||||||
|
providedIn: 'root'
|
||||||
|
})
|
||||||
|
export class TaskseriesService {
|
||||||
|
|
||||||
|
protected basePath = 'http://127.0.0.1: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;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* daily repeating task creation
|
||||||
|
* Creates a daily repeating task
|
||||||
|
* @param taskID internal id of taskgroup
|
||||||
|
* @param taskRepeatDayInfo
|
||||||
|
* @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 tasksTaskIDTaskseriesDailyPost(taskID: number, taskRepeatDayInfo?: TaskRepeatDayInfo, observe?: 'body', reportProgress?: boolean, options?: {httpHeaderAccept?: 'application/json', context?: HttpContext}): Observable<SimpleStatusResponse>;
|
||||||
|
public tasksTaskIDTaskseriesDailyPost(taskID: number, taskRepeatDayInfo?: TaskRepeatDayInfo, observe?: 'response', reportProgress?: boolean, options?: {httpHeaderAccept?: 'application/json', context?: HttpContext}): Observable<HttpResponse<SimpleStatusResponse>>;
|
||||||
|
public tasksTaskIDTaskseriesDailyPost(taskID: number, taskRepeatDayInfo?: TaskRepeatDayInfo, observe?: 'events', reportProgress?: boolean, options?: {httpHeaderAccept?: 'application/json', context?: HttpContext}): Observable<HttpEvent<SimpleStatusResponse>>;
|
||||||
|
public tasksTaskIDTaskseriesDailyPost(taskID: number, taskRepeatDayInfo?: TaskRepeatDayInfo, 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 tasksTaskIDTaskseriesDailyPost.');
|
||||||
|
}
|
||||||
|
|
||||||
|
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();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// to determine the Content-Type header
|
||||||
|
const consumes: string[] = [
|
||||||
|
'application/json'
|
||||||
|
];
|
||||||
|
const httpContentTypeSelected: string | undefined = this.configuration.selectHeaderContentType(consumes);
|
||||||
|
if (httpContentTypeSelected !== undefined) {
|
||||||
|
localVarHeaders = localVarHeaders.set('Content-Type', httpContentTypeSelected);
|
||||||
|
}
|
||||||
|
|
||||||
|
let responseType_: 'text' | 'json' = 'json';
|
||||||
|
if(localVarHttpHeaderAcceptSelected && localVarHttpHeaderAcceptSelected.startsWith('text')) {
|
||||||
|
responseType_ = 'text';
|
||||||
|
}
|
||||||
|
|
||||||
|
return this.httpClient.post<SimpleStatusResponse>(`${this.configuration.basePath}/tasks/${encodeURIComponent(String(taskID))}/taskseries/daily`,
|
||||||
|
taskRepeatDayInfo,
|
||||||
|
{
|
||||||
|
context: localVarHttpContext,
|
||||||
|
responseType: <any>responseType_,
|
||||||
|
withCredentials: this.configuration.withCredentials,
|
||||||
|
headers: localVarHeaders,
|
||||||
|
observe: observe,
|
||||||
|
reportProgress: reportProgress
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* daily repeating task creation
|
||||||
|
* Creates a daily repeating task
|
||||||
|
* @param taskRepeatWeekInfo
|
||||||
|
* @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 tasksTaskseriesWeeklyPost(taskRepeatWeekInfo?: TaskRepeatWeekInfo, observe?: 'body', reportProgress?: boolean, options?: {httpHeaderAccept?: 'application/json', context?: HttpContext}): Observable<SimpleStatusResponse>;
|
||||||
|
public tasksTaskseriesWeeklyPost(taskRepeatWeekInfo?: TaskRepeatWeekInfo, observe?: 'response', reportProgress?: boolean, options?: {httpHeaderAccept?: 'application/json', context?: HttpContext}): Observable<HttpResponse<SimpleStatusResponse>>;
|
||||||
|
public tasksTaskseriesWeeklyPost(taskRepeatWeekInfo?: TaskRepeatWeekInfo, observe?: 'events', reportProgress?: boolean, options?: {httpHeaderAccept?: 'application/json', context?: HttpContext}): Observable<HttpEvent<SimpleStatusResponse>>;
|
||||||
|
public tasksTaskseriesWeeklyPost(taskRepeatWeekInfo?: TaskRepeatWeekInfo, 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();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// to determine the Content-Type header
|
||||||
|
const consumes: string[] = [
|
||||||
|
'application/json'
|
||||||
|
];
|
||||||
|
const httpContentTypeSelected: string | undefined = this.configuration.selectHeaderContentType(consumes);
|
||||||
|
if (httpContentTypeSelected !== undefined) {
|
||||||
|
localVarHeaders = localVarHeaders.set('Content-Type', httpContentTypeSelected);
|
||||||
|
}
|
||||||
|
|
||||||
|
let responseType_: 'text' | 'json' = 'json';
|
||||||
|
if(localVarHttpHeaderAcceptSelected && localVarHttpHeaderAcceptSelected.startsWith('text')) {
|
||||||
|
responseType_ = 'text';
|
||||||
|
}
|
||||||
|
|
||||||
|
return this.httpClient.post<SimpleStatusResponse>(`${this.configuration.basePath}/tasks/taskseries/weekly`,
|
||||||
|
taskRepeatWeekInfo,
|
||||||
|
{
|
||||||
|
context: localVarHttpContext,
|
||||||
|
responseType: <any>responseType_,
|
||||||
|
withCredentials: this.configuration.withCredentials,
|
||||||
|
headers: localVarHeaders,
|
||||||
|
observe: observe,
|
||||||
|
reportProgress: reportProgress
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -29,6 +29,9 @@ export * from './simpleStatusResponse';
|
|||||||
export * from './taskEntityInfo';
|
export * from './taskEntityInfo';
|
||||||
export * from './taskFieldInfo';
|
export * from './taskFieldInfo';
|
||||||
export * from './taskOverviewInfo';
|
export * from './taskOverviewInfo';
|
||||||
|
export * from './taskRepeatDayInfo';
|
||||||
|
export * from './taskRepeatWeekDayInfo';
|
||||||
|
export * from './taskRepeatWeekInfo';
|
||||||
export * from './taskScheduleStopResponse';
|
export * from './taskScheduleStopResponse';
|
||||||
export * from './taskShortInfo';
|
export * from './taskShortInfo';
|
||||||
export * from './taskTaskgroupInfo';
|
export * from './taskTaskgroupInfo';
|
||||||
|
@ -23,7 +23,7 @@ export interface NtfyInformation {
|
|||||||
/**
|
/**
|
||||||
* username of ntfy account for publishing news
|
* username of ntfy account for publishing news
|
||||||
*/
|
*/
|
||||||
ntfy_user: string;
|
ntfy_user?: string;
|
||||||
/**
|
/**
|
||||||
* token to ntfy useraccount
|
* token to ntfy useraccount
|
||||||
*/
|
*/
|
||||||
|
@ -56,5 +56,9 @@ export interface TaskEntityInfo {
|
|||||||
* determines whether the task has schedules that can be started
|
* determines whether the task has schedules that can be started
|
||||||
*/
|
*/
|
||||||
hasPlannedSchedules: boolean;
|
hasPlannedSchedules: boolean;
|
||||||
|
/**
|
||||||
|
* determines whether the task is associated with a taskserie
|
||||||
|
*/
|
||||||
|
hasTaskSerie: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
33
frontend/src/api/model/taskRepeatDayInfo.ts
Normal file
33
frontend/src/api/model/taskRepeatDayInfo.ts
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
/**
|
||||||
|
* 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 TaskRepeatDayInfo {
|
||||||
|
/**
|
||||||
|
* number repeating days
|
||||||
|
*/
|
||||||
|
offset: number;
|
||||||
|
deadlineStrategy: TaskRepeatDayInfo.DeadlineStrategyEnum;
|
||||||
|
/**
|
||||||
|
* Date until the tasks repeat
|
||||||
|
*/
|
||||||
|
endingDate: string;
|
||||||
|
}
|
||||||
|
export namespace TaskRepeatDayInfo {
|
||||||
|
export type DeadlineStrategyEnum = 'DEADLINE_EQUAL_START' | 'DEADLINE_FIT_START';
|
||||||
|
export const DeadlineStrategyEnum = {
|
||||||
|
EqualStart: 'DEADLINE_EQUAL_START' as DeadlineStrategyEnum,
|
||||||
|
FitStart: 'DEADLINE_FIT_START' as DeadlineStrategyEnum
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
|
24
frontend/src/api/model/taskRepeatWeekDayInfo.ts
Normal file
24
frontend/src/api/model/taskRepeatWeekDayInfo.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 TaskRepeatWeekDayInfo {
|
||||||
|
/**
|
||||||
|
* number repeating days
|
||||||
|
*/
|
||||||
|
offset: number;
|
||||||
|
/**
|
||||||
|
* internal identifier of task
|
||||||
|
*/
|
||||||
|
taskID: number;
|
||||||
|
}
|
||||||
|
|
31
frontend/src/api/model/taskRepeatWeekInfo.ts
Normal file
31
frontend/src/api/model/taskRepeatWeekInfo.ts
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
/**
|
||||||
|
* 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 { TaskRepeatWeekDayInfo } from './taskRepeatWeekDayInfo';
|
||||||
|
|
||||||
|
|
||||||
|
export interface TaskRepeatWeekInfo {
|
||||||
|
deadlineStrategy: TaskRepeatWeekInfo.DeadlineStrategyEnum;
|
||||||
|
/**
|
||||||
|
* Date until the tasks repeat
|
||||||
|
*/
|
||||||
|
endDate: string;
|
||||||
|
weekDayInfos: Array<TaskRepeatWeekDayInfo>;
|
||||||
|
}
|
||||||
|
export namespace TaskRepeatWeekInfo {
|
||||||
|
export type DeadlineStrategyEnum = 'DEADLINE_EQUAL_START' | 'DEADLINE_FIT_START';
|
||||||
|
export const DeadlineStrategyEnum = {
|
||||||
|
EqualStart: 'DEADLINE_EQUAL_START' as DeadlineStrategyEnum,
|
||||||
|
FitStart: 'DEADLINE_FIT_START' as DeadlineStrategyEnum
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
|
@ -91,6 +91,9 @@ import {MatGridListModule} from "@angular/material/grid-list";
|
|||||||
import { StopScheduleManuallyComponent } from './dashboard/active-schedule/stop-schedule-manually/stop-schedule-manually.component';
|
import { StopScheduleManuallyComponent } from './dashboard/active-schedule/stop-schedule-manually/stop-schedule-manually.component';
|
||||||
import { ConnectionSettingsComponent } from './user-settings/connection-settings/connection-settings.component';
|
import { ConnectionSettingsComponent } from './user-settings/connection-settings/connection-settings.component';
|
||||||
import { NtfySettingsComponent } from './user-settings/connection-settings/ntfy-settings/ntfy-settings.component';
|
import { NtfySettingsComponent } from './user-settings/connection-settings/ntfy-settings/ntfy-settings.component';
|
||||||
|
import { TaskSeriesCreatorComponent } from './tasks/task-series-creator/task-series-creator.component';
|
||||||
|
import {MatStepperModule} from "@angular/material/stepper";
|
||||||
|
import { TaskWeeklySeriesCreatorComponent } from './tasks/task-weekly-series-creator/task-weekly-series-creator.component';
|
||||||
@NgModule({
|
@NgModule({
|
||||||
declarations: [
|
declarations: [
|
||||||
AppComponent,
|
AppComponent,
|
||||||
@ -138,6 +141,8 @@ import { NtfySettingsComponent } from './user-settings/connection-settings/ntfy-
|
|||||||
StopScheduleManuallyComponent,
|
StopScheduleManuallyComponent,
|
||||||
ConnectionSettingsComponent,
|
ConnectionSettingsComponent,
|
||||||
NtfySettingsComponent,
|
NtfySettingsComponent,
|
||||||
|
TaskSeriesCreatorComponent,
|
||||||
|
TaskWeeklySeriesCreatorComponent,
|
||||||
],
|
],
|
||||||
imports: [
|
imports: [
|
||||||
BrowserModule,
|
BrowserModule,
|
||||||
@ -181,6 +186,7 @@ import { NtfySettingsComponent } from './user-settings/connection-settings/ntfy-
|
|||||||
NgApexchartsModule,
|
NgApexchartsModule,
|
||||||
MatButtonToggleModule,
|
MatButtonToggleModule,
|
||||||
MatGridListModule,
|
MatGridListModule,
|
||||||
|
MatStepperModule,
|
||||||
],
|
],
|
||||||
providers: [
|
providers: [
|
||||||
HttpClientModule,
|
HttpClientModule,
|
||||||
|
@ -20,7 +20,7 @@ td, th {
|
|||||||
margin: 0 auto;
|
margin: 0 auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
.mat-column-status, .mat-column-eta {
|
.mat-column-status, .mat-column-eta, .mat-column-select {
|
||||||
width: 32px;
|
width: 32px;
|
||||||
text-align: left;
|
text-align: left;
|
||||||
}
|
}
|
||||||
|
@ -8,6 +8,23 @@
|
|||||||
|
|
||||||
<div class="mat-elevation-z8">
|
<div class="mat-elevation-z8">
|
||||||
<table mat-table [dataSource]="datasource" matSort>
|
<table mat-table [dataSource]="datasource" matSort>
|
||||||
|
<!-- Checkbox Column -->
|
||||||
|
<ng-container matColumnDef="select">
|
||||||
|
<th mat-header-cell *matHeaderCellDef>
|
||||||
|
<mat-checkbox (change)="$event ? toggleAllRows() : null"
|
||||||
|
[checked]="selection.hasValue() && isAllSelected()"
|
||||||
|
[indeterminate]="selection.hasValue() && !isAllSelected()">
|
||||||
|
</mat-checkbox>
|
||||||
|
</th>
|
||||||
|
<td mat-cell *matCellDef="let row">
|
||||||
|
<mat-checkbox (click)="$event.stopPropagation()"
|
||||||
|
(change)="$event ? selection.toggle(row) : null"
|
||||||
|
[checked]="selection.isSelected(row)"
|
||||||
|
[disabled]="row.hasTaskSerie">
|
||||||
|
</mat-checkbox>
|
||||||
|
</td>
|
||||||
|
</ng-container>
|
||||||
|
|
||||||
<ng-container matColumnDef="name">
|
<ng-container matColumnDef="name">
|
||||||
<th mat-header-cell *matHeaderCellDef mat-sort-header> Name </th>
|
<th mat-header-cell *matHeaderCellDef mat-sort-header> Name </th>
|
||||||
<td mat-cell *matCellDef="let task">
|
<td mat-cell *matCellDef="let task">
|
||||||
@ -45,7 +62,9 @@
|
|||||||
</td>
|
</td>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
<ng-container matColumnDef="delete">
|
<ng-container matColumnDef="delete">
|
||||||
<th mat-header-cell *matHeaderCellDef mat-sort-header></th>
|
<th mat-header-cell *matHeaderCellDef mat-sort-header>
|
||||||
|
<button mat-icon-button color="primary" (click)="repeatSelectedTasks()" [disabled]="selection.isEmpty()"><mat-icon>event_repeat</mat-icon></button>
|
||||||
|
</th>
|
||||||
<td mat-cell *matCellDef="let task">
|
<td mat-cell *matCellDef="let task">
|
||||||
<button mat-icon-button color="warn" (click)="deleteTask(task)"><mat-icon>delete</mat-icon></button>
|
<button mat-icon-button color="warn" (click)="deleteTask(task)"><mat-icon>delete</mat-icon></button>
|
||||||
</td>
|
</td>
|
||||||
|
@ -10,6 +10,8 @@ import {MatSnackBar} from "@angular/material/snack-bar";
|
|||||||
import {ClearTaskDialogComponent, ClearTaskDialogData} from "../clear-task-dialog/clear-task-dialog.component";
|
import {ClearTaskDialogComponent, ClearTaskDialogData} from "../clear-task-dialog/clear-task-dialog.component";
|
||||||
import * as moment from "moment/moment";
|
import * as moment from "moment/moment";
|
||||||
import {TaskStatus, TaskStatusService} from "../task-status.service";
|
import {TaskStatus, TaskStatusService} from "../task-status.service";
|
||||||
|
import {SelectionModel} from "@angular/cdk/collections";
|
||||||
|
import {TaskWeeklySeriesCreatorComponent} from "../task-weekly-series-creator/task-weekly-series-creator.component";
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-task-dashboard',
|
selector: 'app-task-dashboard',
|
||||||
@ -19,15 +21,7 @@ import {TaskStatus, TaskStatusService} from "../task-status.service";
|
|||||||
export class TaskDashboardComponent implements OnChanges{
|
export class TaskDashboardComponent implements OnChanges{
|
||||||
ngOnChanges(): void {
|
ngOnChanges(): void {
|
||||||
if(this.taskgroupID != undefined) {
|
if(this.taskgroupID != undefined) {
|
||||||
this.taskService.tasksTaskgroupIDStatusGet(this.taskgroupID!, "all").subscribe({
|
this.fetchTasks()
|
||||||
next: resp => {
|
|
||||||
this.datasource = new MatTableDataSource<TaskEntityInfo>(resp);
|
|
||||||
this.datasource.paginator = this.paginator!;
|
|
||||||
this.datasource.sort = this.sort!;
|
|
||||||
|
|
||||||
resp.forEach(task => console.log(task))
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -35,9 +29,29 @@ export class TaskDashboardComponent implements OnChanges{
|
|||||||
@ViewChild(MatPaginator) paginator: MatPaginator | undefined
|
@ViewChild(MatPaginator) paginator: MatPaginator | undefined
|
||||||
@ViewChild(MatSort) sort: MatSort | undefined
|
@ViewChild(MatSort) sort: MatSort | undefined
|
||||||
|
|
||||||
displayedColumns: string[] = ['status', 'name', 'eta', 'start', 'deadline', 'finished', 'edit', 'delete'];
|
displayedColumns: string[] = ['select', 'status', 'name', 'eta', 'start', 'deadline', 'finished', 'edit', 'delete'];
|
||||||
datasource: MatTableDataSource<TaskEntityInfo> = new MatTableDataSource<TaskEntityInfo>();
|
datasource: MatTableDataSource<TaskEntityInfo> = new MatTableDataSource<TaskEntityInfo>();
|
||||||
|
|
||||||
|
selection = new SelectionModel<TaskEntityInfo>(true, []);
|
||||||
|
|
||||||
|
/** Whether the number of selected elements matches the total number of rows. */
|
||||||
|
isAllSelected() {
|
||||||
|
const numSelected = this.selection.selected.length;
|
||||||
|
const numRows = this.datasource.data.length;
|
||||||
|
return numSelected === numRows;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Selects all rows if they are not all selected; otherwise clear selection. */
|
||||||
|
toggleAllRows() {
|
||||||
|
if (this.isAllSelected()) {
|
||||||
|
this.selection.clear();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.selection.select(...this.datasource.data.filter(task => !task.hasTaskSerie));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
constructor(private taskService: TaskService,
|
constructor(private taskService: TaskService,
|
||||||
private dialog: MatDialog,
|
private dialog: MatDialog,
|
||||||
private snackbar: MatSnackBar,
|
private snackbar: MatSnackBar,
|
||||||
@ -107,4 +121,30 @@ export class TaskDashboardComponent implements OnChanges{
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected readonly TaskStatus = TaskStatus;
|
protected readonly TaskStatus = TaskStatus;
|
||||||
|
|
||||||
|
repeatSelectedTasks() {
|
||||||
|
const selectedTasks = this.selection.selected;
|
||||||
|
const dialogRef = this.dialog.open(TaskWeeklySeriesCreatorComponent, {
|
||||||
|
data: selectedTasks,
|
||||||
|
minWidth: "400px"
|
||||||
|
});
|
||||||
|
dialogRef.afterClosed().subscribe(res => {
|
||||||
|
if(res) {
|
||||||
|
this.fetchTasks()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
fetchTasks() {
|
||||||
|
this.taskService.tasksTaskgroupIDStatusGet(this.taskgroupID!, "all").subscribe({
|
||||||
|
next: resp => {
|
||||||
|
this.datasource = new MatTableDataSource<TaskEntityInfo>(resp);
|
||||||
|
this.datasource.paginator = this.paginator!;
|
||||||
|
this.datasource.sort = this.sort!;
|
||||||
|
|
||||||
|
resp.forEach(task => console.log(task))
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -29,7 +29,7 @@
|
|||||||
<button mat-flat-button class="borderless-btn" color="primary" [routerLink]="['/taskgroups', taskgroup!.taskgroupID, 'tasks', task!.taskID, 'schedule']">Schedule</button>
|
<button mat-flat-button class="borderless-btn" color="primary" [routerLink]="['/taskgroups', taskgroup!.taskgroupID, 'tasks', task!.taskID, 'schedule']">Schedule</button>
|
||||||
<button mat-flat-button class="yellowBtn" (click)="startTaskNow()">Start now</button>
|
<button mat-flat-button class="yellowBtn" (click)="startTaskNow()">Start now</button>
|
||||||
<button mat-flat-button class="grayBtn" (click)="openTaskEditor()">Edit</button>
|
<button mat-flat-button class="grayBtn" (click)="openTaskEditor()">Edit</button>
|
||||||
<!--<button mat-raised-button>Copy</button>-->
|
<button mat-flat-button class="lightBlueBtn" *ngIf="!task.hasTaskSerie" (click)="openRepeatingTaskEditor()">Copy</button>
|
||||||
<button mat-flat-button class="greenBtn" *ngIf="task!.finishable" (click)="finishTask()">{{task!.finished ? 'Reopen':'Finish'}}</button>
|
<button mat-flat-button class="greenBtn" *ngIf="task!.finishable" (click)="finishTask()">{{task!.finished ? 'Reopen':'Finish'}}</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@ -17,6 +17,7 @@ import {TaskEditorData} from "../task-editor/TaskEditorData";
|
|||||||
import * as moment from "moment";
|
import * as moment from "moment";
|
||||||
import {ScheduleDashboardComponent} from "../../schedules/schedule-dashboard/schedule-dashboard.component";
|
import {ScheduleDashboardComponent} from "../../schedules/schedule-dashboard/schedule-dashboard.component";
|
||||||
import {TaskStatusService} from "../task-status.service";
|
import {TaskStatusService} from "../task-status.service";
|
||||||
|
import {TaskSeriesCreatorComponent} from "../task-series-creator/task-series-creator.component";
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-task-detail-overview',
|
selector: 'app-task-detail-overview',
|
||||||
@ -158,4 +159,11 @@ export class TaskDetailOverviewComponent implements OnInit {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
openRepeatingTaskEditor() {
|
||||||
|
const dialogRef = this.dialog.open(TaskSeriesCreatorComponent, {
|
||||||
|
data: this.task!,
|
||||||
|
minWidth: "400px"
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,37 @@
|
|||||||
|
<h1 mat-dialog-title>Create Task-Series</h1>
|
||||||
|
<mat-stepper linear="linear" #stepper orientation="vertical">
|
||||||
|
<mat-step [stepControl]="dailyFormGroup">
|
||||||
|
<form [formGroup]="dailyFormGroup">
|
||||||
|
<ng-template matStepLabel>Define Repeating Information</ng-template>
|
||||||
|
<mat-form-field appearance="outline" class="long-form">
|
||||||
|
<mat-label>Offset</mat-label>
|
||||||
|
<input matInput formControlName="offsetCtrl" type="number" (keypress)="($event.charCode >= 48 && $event.charCode < 58)">
|
||||||
|
</mat-form-field>
|
||||||
|
<mat-form-field appearance="outline" class="long-form">
|
||||||
|
<mat-label>Deadline Strategy</mat-label>
|
||||||
|
<mat-select formControlName="deadlineStrategyCtrl">
|
||||||
|
<mat-option value="DEADLINE_FIT_START">Fit Next Start</mat-option>
|
||||||
|
<mat-option value="DEADLINE_EQUAL_START">Equal Same Start</mat-option>
|
||||||
|
</mat-select>
|
||||||
|
</mat-form-field>
|
||||||
|
<div>
|
||||||
|
<button mat-raised-button color="primary" matStepperNext>Next</button>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</mat-step>
|
||||||
|
<mat-step [stepControl]="endDateFormGroup">
|
||||||
|
<form [formGroup]="endDateFormGroup">
|
||||||
|
<ng-template matStepLabel>When should the TaskSerie end?</ng-template>
|
||||||
|
<mat-form-field appearance="outline" class="long-form">
|
||||||
|
<mat-label>Choose a date</mat-label>
|
||||||
|
<input matInput [matDatepicker]="picker" formControlName="endDateCtrl">
|
||||||
|
<mat-hint>MM/DD/YYYY</mat-hint>
|
||||||
|
<mat-datepicker-toggle matIconSuffix [for]="picker"></mat-datepicker-toggle>
|
||||||
|
<mat-datepicker #picker></mat-datepicker>
|
||||||
|
</mat-form-field>
|
||||||
|
<div>
|
||||||
|
<button mat-raised-button color="primary" (click)="save()">Submit</button>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</mat-step>
|
||||||
|
</mat-stepper>
|
@ -0,0 +1,21 @@
|
|||||||
|
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||||
|
|
||||||
|
import { TaskSeriesCreatorComponent } from './task-series-creator.component';
|
||||||
|
|
||||||
|
describe('TaskSeriesCreatorComponent', () => {
|
||||||
|
let component: TaskSeriesCreatorComponent;
|
||||||
|
let fixture: ComponentFixture<TaskSeriesCreatorComponent>;
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
TestBed.configureTestingModule({
|
||||||
|
declarations: [TaskSeriesCreatorComponent]
|
||||||
|
});
|
||||||
|
fixture = TestBed.createComponent(TaskSeriesCreatorComponent);
|
||||||
|
component = fixture.componentInstance;
|
||||||
|
fixture.detectChanges();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should create', () => {
|
||||||
|
expect(component).toBeTruthy();
|
||||||
|
});
|
||||||
|
});
|
@ -0,0 +1,52 @@
|
|||||||
|
import {Component, Inject} from '@angular/core';
|
||||||
|
import {FormBuilder, Validators} from "@angular/forms";
|
||||||
|
import {TaskEntityInfo, TaskRepeatDayInfo, TaskseriesService} from "../../../api";
|
||||||
|
import {MAT_DIALOG_DATA, MatDialogRef} from "@angular/material/dialog";
|
||||||
|
import DeadlineStrategyEnum = TaskRepeatDayInfo.DeadlineStrategyEnum;
|
||||||
|
import * as moment from "moment";
|
||||||
|
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-task-series-creator',
|
||||||
|
templateUrl: './task-series-creator.component.html',
|
||||||
|
styleUrls: ['./task-series-creator.component.css']
|
||||||
|
})
|
||||||
|
export class TaskSeriesCreatorComponent {
|
||||||
|
|
||||||
|
dailyFormGroup = this._formBuilder.group({
|
||||||
|
offsetCtrl: ['', Validators.required],
|
||||||
|
deadlineStrategyCtrl: ['', Validators.required]
|
||||||
|
})
|
||||||
|
|
||||||
|
endDateFormGroup = this._formBuilder.group({
|
||||||
|
endDateCtrl: ['', Validators.required]
|
||||||
|
})
|
||||||
|
|
||||||
|
constructor(private _formBuilder: FormBuilder,
|
||||||
|
private taskSeriesService: TaskseriesService,
|
||||||
|
@Inject(MAT_DIALOG_DATA) public task: TaskEntityInfo,
|
||||||
|
private dialogRef: MatDialogRef<TaskSeriesCreatorComponent>) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
save() {
|
||||||
|
this.taskSeriesService.tasksTaskIDTaskseriesDailyPost(this.task.taskID,{
|
||||||
|
offset: Number(this.dailyFormGroup.get('offsetCtrl')!.value!),
|
||||||
|
deadlineStrategy: this.convertDeadlineStrategyCtrlToDeadlineEnum(),
|
||||||
|
endingDate: moment( this.endDateFormGroup.get('endDateCtrl')!.value!).format('YYYY-MM-DDTHH:mm:ss.SSSZ')
|
||||||
|
}).subscribe({
|
||||||
|
next: resp => {
|
||||||
|
this.dialogRef.close();
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
convertDeadlineStrategyCtrlToDeadlineEnum() {
|
||||||
|
const deadlineStrategy = this.dailyFormGroup.get('deadlineStrategyCtrl')!.value;
|
||||||
|
if(deadlineStrategy === DeadlineStrategyEnum.EqualStart) {
|
||||||
|
return DeadlineStrategyEnum.EqualStart;
|
||||||
|
} else {
|
||||||
|
return DeadlineStrategyEnum.FitStart;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,10 @@
|
|||||||
|
#deadline-strategy-form {
|
||||||
|
margin-top: 10px;
|
||||||
|
padding-left: 10px;
|
||||||
|
padding-right: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endDate-form {
|
||||||
|
padding-left: 10px;
|
||||||
|
padding-right: 10px;
|
||||||
|
}
|
@ -0,0 +1,50 @@
|
|||||||
|
<h1 mat-dialog-title>Configure Weekly Repeating Tasks</h1>
|
||||||
|
<form [formGroup]="repeatingOffsetForm" *ngIf="repeatingOffsetForm != undefined">
|
||||||
|
<div formArrayName="offsets">
|
||||||
|
<mat-accordion>
|
||||||
|
<div *ngFor="let task of offsets.controls; let i = index" [formGroupName]="i">
|
||||||
|
<mat-expansion-panel hideToggle>
|
||||||
|
<mat-expansion-panel-header>
|
||||||
|
<mat-panel-title>{{getDayOfWeek(tasks[i].startDate)}}</mat-panel-title>
|
||||||
|
<mat-panel-description>{{formatDate(tasks[i].startDate)}}</mat-panel-description>
|
||||||
|
</mat-expansion-panel-header>
|
||||||
|
<p>Taskname: {{tasks[i].taskName}}</p>
|
||||||
|
<p>Eta: {{tasks[i].eta}} Minutes</p>
|
||||||
|
<p>Startdate: {{formatDate(tasks[i].startDate)}}</p>
|
||||||
|
<p>Deadline: {{formatDate(tasks[i].deadline)}}</p>
|
||||||
|
<mat-form-field appearance="outline" class="long-form">
|
||||||
|
<mat-label>Repeating-Offset</mat-label>
|
||||||
|
<input matInput formControlName="offsetCtrl">
|
||||||
|
<mat-hint>Number of weeks until the task is to be repeated</mat-hint>
|
||||||
|
</mat-form-field>
|
||||||
|
<mat-action-row>
|
||||||
|
<button mat-icon-button color="warn" (click)="removeTaskFromRepeatingList(tasks[i], i)"><mat-icon>delete</mat-icon></button>
|
||||||
|
</mat-action-row>
|
||||||
|
</mat-expansion-panel>
|
||||||
|
</div>
|
||||||
|
</mat-accordion>
|
||||||
|
</div>
|
||||||
|
<mat-form-field appearance="outline" class="long-form" id="deadline-strategy-form">
|
||||||
|
<mat-label>Deadline-Strategy</mat-label>
|
||||||
|
<mat-select formControlName="deadlineStrategyCtrl">
|
||||||
|
<mat-option *ngFor="let deadlineStrategy of availableDeadlineStrategys" [value]="deadlineStrategy">
|
||||||
|
{{deadlineStrategy}}
|
||||||
|
</mat-option>
|
||||||
|
</mat-select>
|
||||||
|
</mat-form-field>
|
||||||
|
|
||||||
|
<mat-form-field appearance="outline" class="long-form" id="endDate-form">
|
||||||
|
<mat-label>Ending Date</mat-label>
|
||||||
|
<input matInput [matDatepicker]="picker" formControlName="endingDateCtrl">
|
||||||
|
<mat-hint>MM/DD/YYYY</mat-hint>
|
||||||
|
<mat-datepicker-toggle matIconSuffix [for]="picker"></mat-datepicker-toggle>
|
||||||
|
<mat-datepicker #picker></mat-datepicker>
|
||||||
|
</mat-form-field>
|
||||||
|
|
||||||
|
<div mat-dialog-actions align="end">
|
||||||
|
<button mat-raised-button (click)="cancel()">Cancel</button>
|
||||||
|
<button mat-raised-button color="primary" [disabled]="repeatingOffsetForm.invalid" (click)="saveRepeatingTask()">Save</button>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
|
||||||
|
|
@ -0,0 +1,21 @@
|
|||||||
|
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||||
|
|
||||||
|
import { TaskWeeklySeriesCreatorComponent } from './task-weekly-series-creator.component';
|
||||||
|
|
||||||
|
describe('TaskWeeklySeriesCreatorComponent', () => {
|
||||||
|
let component: TaskWeeklySeriesCreatorComponent;
|
||||||
|
let fixture: ComponentFixture<TaskWeeklySeriesCreatorComponent>;
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
TestBed.configureTestingModule({
|
||||||
|
declarations: [TaskWeeklySeriesCreatorComponent]
|
||||||
|
});
|
||||||
|
fixture = TestBed.createComponent(TaskWeeklySeriesCreatorComponent);
|
||||||
|
component = fixture.componentInstance;
|
||||||
|
fixture.detectChanges();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should create', () => {
|
||||||
|
expect(component).toBeTruthy();
|
||||||
|
});
|
||||||
|
});
|
@ -0,0 +1,83 @@
|
|||||||
|
import {Component, Inject, OnInit} from '@angular/core';
|
||||||
|
import {MAT_DIALOG_DATA, MatDialogRef} from "@angular/material/dialog";
|
||||||
|
import {TaskEntityInfo, TaskRepeatDayInfo, TaskRepeatWeekDayInfo, TaskseriesService} from "../../../api";
|
||||||
|
import * as moment from "moment";
|
||||||
|
import {FormArray, FormBuilder, FormGroup, Validators} from "@angular/forms";
|
||||||
|
import DeadlineStrategyEnum = TaskRepeatDayInfo.DeadlineStrategyEnum;
|
||||||
|
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-task-weekly-series-creator',
|
||||||
|
templateUrl: './task-weekly-series-creator.component.html',
|
||||||
|
styleUrls: ['./task-weekly-series-creator.component.css']
|
||||||
|
})
|
||||||
|
export class TaskWeeklySeriesCreatorComponent implements OnInit{
|
||||||
|
|
||||||
|
repeatingOffsetForm: FormGroup | undefined
|
||||||
|
availableDeadlineStrategys: DeadlineStrategyEnum[] = ["DEADLINE_EQUAL_START", "DEADLINE_FIT_START"]
|
||||||
|
|
||||||
|
constructor(private dialogRef: MatDialogRef<TaskWeeklySeriesCreatorComponent>,
|
||||||
|
private taskRepeatingService: TaskseriesService,
|
||||||
|
@Inject(MAT_DIALOG_DATA) public tasks: TaskEntityInfo[],
|
||||||
|
private formbuilder: FormBuilder) {
|
||||||
|
}
|
||||||
|
|
||||||
|
ngOnInit(): void {
|
||||||
|
this.repeatingOffsetForm = this.formbuilder.group({
|
||||||
|
offsets: this.formbuilder.array(this.tasks.map(task => this.formbuilder.group({
|
||||||
|
offsetCtrl: ['', [Validators.required, Validators.min(1)]]
|
||||||
|
}))),
|
||||||
|
deadlineStrategyCtrl: ['', Validators.required],
|
||||||
|
endingDateCtrl: ['', Validators.required]
|
||||||
|
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
getDayOfWeek(date: string) {
|
||||||
|
return moment(date).format("dddd")
|
||||||
|
}
|
||||||
|
|
||||||
|
formatDate(date: string): string {
|
||||||
|
return moment(date).format("dd, DD. MMMM YYYY")
|
||||||
|
}
|
||||||
|
|
||||||
|
removeTaskFromRepeatingList(task: TaskEntityInfo, formIndex: number) {
|
||||||
|
this.tasks = this.tasks.filter(t => t.taskID !== task.taskID);
|
||||||
|
this.deleteOffset(formIndex)
|
||||||
|
}
|
||||||
|
|
||||||
|
get offsets() {
|
||||||
|
return this.repeatingOffsetForm!.controls["offsets"] as FormArray
|
||||||
|
}
|
||||||
|
|
||||||
|
deleteOffset(taskIndex: number) {
|
||||||
|
this.offsets.removeAt(taskIndex);
|
||||||
|
}
|
||||||
|
|
||||||
|
saveRepeatingTask() {
|
||||||
|
const weekDayInfos: TaskRepeatWeekDayInfo[] = []
|
||||||
|
const formArrayValues: {offsetCtrl: string}[] = this.offsets.value
|
||||||
|
for(let i=0; i<formArrayValues.length; i++) {
|
||||||
|
weekDayInfos.push({
|
||||||
|
taskID: this.tasks[i].taskID,
|
||||||
|
offset: Number(formArrayValues[i].offsetCtrl) * 7
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
this.taskRepeatingService.tasksTaskseriesWeeklyPost({
|
||||||
|
deadlineStrategy: this.repeatingOffsetForm!.controls['deadlineStrategyCtrl']!.value!,
|
||||||
|
endDate: moment(this.repeatingOffsetForm!.controls['endingDateCtrl']!.value!).format('YYYY-MM-DDTHH:mm:ss.SSSZ'),
|
||||||
|
weekDayInfos: weekDayInfos
|
||||||
|
}).subscribe({
|
||||||
|
next: resp => {
|
||||||
|
this.dialogRef.close(true)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
cancel() {
|
||||||
|
this.dialogRef.close(false);
|
||||||
|
}
|
||||||
|
}
|
@ -24,7 +24,7 @@ export class NtfySettingsComponent {
|
|||||||
next: resp => {
|
next: resp => {
|
||||||
this.host_formCtrl.setValue(resp.ntfy_host);
|
this.host_formCtrl.setValue(resp.ntfy_host);
|
||||||
this.topic_formCtrl.setValue(resp.ntfy_topic);
|
this.topic_formCtrl.setValue(resp.ntfy_topic);
|
||||||
this.user_formCtrl.setValue(resp.ntfy_user);
|
this.user_formCtrl.setValue(resp.ntfy_user!);
|
||||||
this.token_formCtrl.setValue(resp.ntfy_token!);
|
this.token_formCtrl.setValue(resp.ntfy_token!);
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
142
openapi.yaml
142
openapi.yaml
@ -2073,6 +2073,84 @@ paths:
|
|||||||
application/json:
|
application/json:
|
||||||
schema:
|
schema:
|
||||||
$ref: '#/components/schemas/SimpleStatusResponse'
|
$ref: '#/components/schemas/SimpleStatusResponse'
|
||||||
|
/tasks/{taskID}/taskseries/daily:
|
||||||
|
post:
|
||||||
|
security:
|
||||||
|
- API_TOKEN: []
|
||||||
|
tags:
|
||||||
|
- taskseries
|
||||||
|
description: Creates a daily repeating task
|
||||||
|
summary: daily repeating task creation
|
||||||
|
parameters:
|
||||||
|
- name: taskID
|
||||||
|
in: path
|
||||||
|
description: internal id of taskgroup
|
||||||
|
required: true
|
||||||
|
schema:
|
||||||
|
type: number
|
||||||
|
example: 1
|
||||||
|
requestBody:
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
$ref: '#/components/schemas/TaskRepeatDayInfo'
|
||||||
|
responses:
|
||||||
|
200:
|
||||||
|
description: Operation successfull
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
$ref: '#/components/schemas/SimpleStatusResponse'
|
||||||
|
403:
|
||||||
|
description: No permission
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
$ref: '#/components/schemas/SimpleStatusResponse'
|
||||||
|
404:
|
||||||
|
description: Task not found
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
$ref: '#/components/schemas/SimpleStatusResponse'
|
||||||
|
400:
|
||||||
|
description: Invalid deadlineStrategy
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
$ref: '#/components/schemas/SimpleStatusResponse'
|
||||||
|
/tasks/taskseries/weekly:
|
||||||
|
post:
|
||||||
|
security:
|
||||||
|
- API_TOKEN: []
|
||||||
|
tags:
|
||||||
|
- taskseries
|
||||||
|
description: Creates a daily repeating task
|
||||||
|
summary: daily repeating task creation
|
||||||
|
requestBody:
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
$ref: '#/components/schemas/TaskRepeatWeekInfo'
|
||||||
|
responses:
|
||||||
|
200:
|
||||||
|
description: Operation successfull
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
$ref: '#/components/schemas/SimpleStatusResponse'
|
||||||
|
403:
|
||||||
|
description: No permission
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
$ref: '#/components/schemas/SimpleStatusResponse'
|
||||||
|
404:
|
||||||
|
description: Task not found
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
$ref: '#/components/schemas/SimpleStatusResponse'
|
||||||
|
|
||||||
|
|
||||||
components:
|
components:
|
||||||
@ -2336,6 +2414,7 @@ components:
|
|||||||
- finishable
|
- finishable
|
||||||
- hasActiveSchedules
|
- hasActiveSchedules
|
||||||
- hasPlannedSchedules
|
- hasPlannedSchedules
|
||||||
|
- hasTaskSerie
|
||||||
additionalProperties: false
|
additionalProperties: false
|
||||||
properties:
|
properties:
|
||||||
taskID:
|
taskID:
|
||||||
@ -2380,6 +2459,10 @@ components:
|
|||||||
hasPlannedSchedules:
|
hasPlannedSchedules:
|
||||||
type: boolean
|
type: boolean
|
||||||
description: determines whether the task has schedules that can be started
|
description: determines whether the task has schedules that can be started
|
||||||
|
hasTaskSerie:
|
||||||
|
type: boolean
|
||||||
|
description: determines whether the task is associated with a taskserie
|
||||||
|
example: false
|
||||||
TaskTaskgroupInfo:
|
TaskTaskgroupInfo:
|
||||||
required:
|
required:
|
||||||
- taskID
|
- taskID
|
||||||
@ -2780,3 +2863,62 @@ components:
|
|||||||
ntfy_token:
|
ntfy_token:
|
||||||
type: string
|
type: string
|
||||||
description: token to ntfy useraccount
|
description: token to ntfy useraccount
|
||||||
|
TaskRepeatDayInfo:
|
||||||
|
required:
|
||||||
|
- offset
|
||||||
|
- deadlineStrategy
|
||||||
|
- endingDate
|
||||||
|
additionalProperties: false
|
||||||
|
properties:
|
||||||
|
offset:
|
||||||
|
type: number
|
||||||
|
description: number repeating days
|
||||||
|
example: 7
|
||||||
|
minimum: 1
|
||||||
|
deadlineStrategy:
|
||||||
|
type: string
|
||||||
|
enum:
|
||||||
|
- DEADLINE_EQUAL_START
|
||||||
|
- DEADLINE_FIT_START
|
||||||
|
endingDate:
|
||||||
|
type: string
|
||||||
|
format: date
|
||||||
|
description: Date until the tasks repeat
|
||||||
|
TaskRepeatWeekDayInfo:
|
||||||
|
required:
|
||||||
|
- offset
|
||||||
|
- taskID
|
||||||
|
additionalProperties: false
|
||||||
|
properties:
|
||||||
|
offset:
|
||||||
|
type: number
|
||||||
|
description: number repeating days
|
||||||
|
example: 7
|
||||||
|
minimum: 1
|
||||||
|
taskID:
|
||||||
|
type: number
|
||||||
|
description: internal identifier of task
|
||||||
|
example: 1
|
||||||
|
TaskRepeatWeekInfo:
|
||||||
|
required:
|
||||||
|
- weekDayInfos
|
||||||
|
- deadlineStrategy
|
||||||
|
- endDate
|
||||||
|
additionalProperties: false
|
||||||
|
properties:
|
||||||
|
deadlineStrategy:
|
||||||
|
type: string
|
||||||
|
enum:
|
||||||
|
- DEADLINE_EQUAL_START
|
||||||
|
- DEADLINE_FIT_START
|
||||||
|
endDate:
|
||||||
|
type: string
|
||||||
|
format: date
|
||||||
|
description: Date until the tasks repeat
|
||||||
|
weekDayInfos:
|
||||||
|
type: array
|
||||||
|
items:
|
||||||
|
$ref: '#/components/schemas/TaskRepeatWeekDayInfo'
|
||||||
|
maxLength: 7
|
||||||
|
minLength: 1
|
||||||
|
|
Loading…
Reference in New Issue
Block a user