diff --git a/backend/.idea/workspace.xml b/backend/.idea/workspace.xml
index fe49c14..76f6eff 100644
--- a/backend/.idea/workspace.xml
+++ b/backend/.idea/workspace.xml
@@ -4,17 +4,34 @@
-
+
+
-
-
+
+
+
+
+
+
+
+
+
+
+
{
@@ -26,28 +43,29 @@
- {
- "keyToString": {
- "RequestMappingsPanelOrder0": "0",
- "RequestMappingsPanelOrder1": "1",
- "RequestMappingsPanelWidth0": "75",
- "RequestMappingsPanelWidth1": "75",
- "RunOnceActivity.OpenProjectViewOnStart": "true",
- "RunOnceActivity.ShowReadmeOnStart": "true",
- "WebServerToolWindowFactoryState": "false",
- "git-widget-placeholder": "issue-7",
- "node.js.detected.package.eslint": "true",
- "node.js.detected.package.tslint": "true",
- "node.js.selected.package.eslint": "(autodetect)",
- "node.js.selected.package.tslint": "(autodetect)",
- "vue.rearranger.settings.migration": "true"
+
+}]]>
@@ -76,7 +94,15 @@
1696188127467
-
+
+
+ 1696233406235
+
+
+
+ 1696233406235
+
+
@@ -84,7 +110,9 @@
-
+
+
+
diff --git a/backend/src/main/java/core/api/controller/TaskController.java b/backend/src/main/java/core/api/controller/TaskController.java
new file mode 100644
index 0000000..20791bb
--- /dev/null
+++ b/backend/src/main/java/core/api/controller/TaskController.java
@@ -0,0 +1,72 @@
+package core.api.controller;
+
+import core.api.models.auth.SimpleStatusResponse;
+import core.api.models.timemanager.tasks.TaskEntityInfo;
+import core.api.models.timemanager.tasks.TaskFieldInfo;
+import core.entities.timemanager.Task;
+import core.entities.timemanager.Taskgroup;
+import core.services.*;
+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 TaskController {
+
+ private final TaskService taskService;
+ private final TaskgroupService taskgroupService;
+
+ public TaskController(@Autowired TaskService taskService, @Autowired TaskgroupService taskgroupService) {
+ this.taskService = taskService;
+ this.taskgroupService = taskgroupService;
+ }
+
+ @GetMapping("/tasks/{taskgroupID}/{status}")
+ public ResponseEntity> listTasksOfTaskgroup(@PathVariable long taskgroupID, @PathVariable String status) {
+ PermissionResult taskgroupPermissionResult = taskgroupService.getTaskgroupByIDAndUsername(taskgroupID, SecurityContextHolder.getContext().getAuthentication().getName());
+ if(!taskgroupPermissionResult.isHasPermissions()) {
+ return ResponseEntity.status(403).body(new SimpleStatusResponse("failed"));
+ }
+
+ if(taskgroupPermissionResult.getExitCode() == ServiceExitCode.MISSING_ENTITY) {
+ return ResponseEntity.status(404).body(new SimpleStatusResponse("failed"));
+ }
+
+
+ if(status.equalsIgnoreCase("all")) {
+ return ResponseEntity.ok(taskgroupPermissionResult.getResult().getTasks().stream().map(TaskEntityInfo::new));
+ } else if(status.equalsIgnoreCase("overdue")) {
+ //List overdue tasks
+ return ResponseEntity.ok(new SimpleStatusResponse("success"));
+ } else if(status.equalsIgnoreCase("upcoming")) {
+ //List upcoming tasks
+ return ResponseEntity.ok(new SimpleStatusResponse("success"));
+ } else {
+ return ResponseEntity.status(404).body(new SimpleStatusResponse("failed"));
+ }
+ }
+
+ @PostMapping("/tasks/{taskgroupID}")
+ public ResponseEntity> createTask(@PathVariable long taskgroupID, @RequestBody @Valid TaskFieldInfo taskFieldInfo) {
+ PermissionResult taskgroupPermissionResult = taskgroupService.getTaskgroupByIDAndUsername(taskgroupID, SecurityContextHolder.getContext().getAuthentication().getName());
+ if(!taskgroupPermissionResult.isHasPermissions()) {
+ return ResponseEntity.status(403).body(new SimpleStatusResponse("failed"));
+ }
+
+ if(taskgroupPermissionResult.getExitCode() == ServiceExitCode.MISSING_ENTITY) {
+ return ResponseEntity.status(404).body(new SimpleStatusResponse("failed"));
+ }
+
+ ServiceResult creationResult = taskService.createTask(taskgroupPermissionResult.getResult(), taskFieldInfo);
+ if(creationResult.getExitCode() == ServiceExitCode.ENTITY_ALREADY_EXIST) {
+ return ResponseEntity.status(409).body(new SimpleStatusResponse("failed"));
+ } else {
+ return ResponseEntity.ok(new TaskEntityInfo(creationResult.getResult()));
+ }
+ }
+}
diff --git a/backend/src/main/java/core/api/models/timemanager/tasks/TaskEntityInfo.java b/backend/src/main/java/core/api/models/timemanager/tasks/TaskEntityInfo.java
index f052ba1..02a7b69 100644
--- a/backend/src/main/java/core/api/models/timemanager/tasks/TaskEntityInfo.java
+++ b/backend/src/main/java/core/api/models/timemanager/tasks/TaskEntityInfo.java
@@ -16,12 +16,15 @@ public class TaskEntityInfo {
private LocalDate deadline;
+ private boolean overdue;
+
public TaskEntityInfo(Task task) {
this.taskID = task.getTaskID();
this.taskName = task.getTaskName();
this.eta = task.getEta();
this.startDate = task.getStartDate();
this.deadline = task.getDeadline();
+ this.overdue = LocalDate.now().isAfter(task.getDeadline());
}
public long getTaskID() {
@@ -63,4 +66,12 @@ public class TaskEntityInfo {
public void setDeadline(LocalDate deadline) {
this.deadline = deadline;
}
+
+ public boolean isOverdue() {
+ return overdue;
+ }
+
+ public void setOverdue(boolean overdue) {
+ this.overdue = overdue;
+ }
}
diff --git a/backend/src/main/java/core/entities/timemanager/Task.java b/backend/src/main/java/core/entities/timemanager/Task.java
index 2621424..5f7446e 100644
--- a/backend/src/main/java/core/entities/timemanager/Task.java
+++ b/backend/src/main/java/core/entities/timemanager/Task.java
@@ -22,9 +22,12 @@ public class Task {
private int eta;
- public Task(Taskgroup taskgroup, String taskName) {
+ public Task(Taskgroup taskgroup, String taskName, LocalDate startDate, LocalDate deadline, int eta) {
this.taskgroup = taskgroup;
this.taskName = taskName;
+ this.startDate = startDate;
+ this.deadline = deadline;
+ this.eta = eta;
}
public Task() {
diff --git a/backend/src/main/java/core/entities/timemanager/Taskgroup.java b/backend/src/main/java/core/entities/timemanager/Taskgroup.java
index 7278502..6e18d60 100644
--- a/backend/src/main/java/core/entities/timemanager/Taskgroup.java
+++ b/backend/src/main/java/core/entities/timemanager/Taskgroup.java
@@ -79,4 +79,12 @@ public class Taskgroup {
public void setParent(Taskgroup parent) {
this.parent = parent;
}
+
+ public Set getTasks() {
+ return tasks;
+ }
+
+ public void setTasks(Set tasks) {
+ this.tasks = tasks;
+ }
}
diff --git a/backend/src/main/java/core/services/TaskService.java b/backend/src/main/java/core/services/TaskService.java
index eff16dc..f9c2020 100644
--- a/backend/src/main/java/core/services/TaskService.java
+++ b/backend/src/main/java/core/services/TaskService.java
@@ -1,9 +1,15 @@
package core.services;
+import core.api.models.timemanager.tasks.TaskFieldInfo;
+import core.entities.timemanager.Task;
+import core.entities.timemanager.Taskgroup;
import core.repositories.timemanager.TaskRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
+import java.util.Collection;
+import java.util.List;
+
@Service
public class TaskService {
@@ -12,4 +18,26 @@ public class TaskService {
public TaskService(@Autowired TaskRepository taskRepository) {
this.taskRepository = taskRepository;
}
+
+ public ServiceResult createTask(Taskgroup taskgroup, TaskFieldInfo taskFieldInfo) {
+ if(existTaskByName(taskgroup.getTasks(), taskFieldInfo.getTaskName())) {
+ return new ServiceResult<>(ServiceExitCode.ENTITY_ALREADY_EXIST);
+ }
+
+
+ Task task = new Task(taskgroup, taskFieldInfo.getTaskName(), taskFieldInfo.getStartDate(), taskFieldInfo.getDeadline(), taskFieldInfo.getEta());
+ taskgroup.getTasks().add(task);
+ taskRepository.save(task);
+
+ return new ServiceResult<>(task);
+ }
+
+ private boolean existTaskByName(Collection tasks, String name) {
+ for(Task task : tasks) {
+ if(task.getTaskName().equals(name)) {
+ return true;
+ }
+ }
+ return false;
+ }
}
diff --git a/openapi.yaml b/openapi.yaml
index af8b5b3..3699910 100644
--- a/openapi.yaml
+++ b/openapi.yaml
@@ -829,6 +829,147 @@ paths:
example: "failed"
enum:
- "failed"
+ /tasks/{taskgroupID}/{status}:
+ get:
+ security:
+ - API_TOKEN: []
+ tags:
+ - task
+ summary: list tasks
+ description: list tasks
+ parameters:
+ - name: taskgroupID
+ in: path
+ description: internal id of taskgroup
+ required: true
+ schema:
+ type: number
+ example: 1
+ - name: status
+ in: path
+ description: scope of listed tasks
+ required: true
+ schema:
+ type: string
+ enum:
+ - all
+ - overdue
+ - upcoming
+ example: all
+ responses:
+ 200:
+ description: Anfrage erfolgreich
+ content:
+ 'application/json':
+ schema:
+ type: array
+ items:
+ $ref: '#/components/schemas/TaskEntityInfo'
+ 403:
+ description: No permission
+ content:
+ 'application/json':
+ schema:
+ type: object
+ required:
+ - status
+ properties:
+ status:
+ type: string
+ description: Status
+ example: "failed"
+ enum:
+ - "failed"
+ 404:
+ description: Taskgroup does not exist
+ content:
+ 'application/json':
+ schema:
+ type: object
+ required:
+ - status
+ properties:
+ status:
+ type: string
+ description: Status
+ example: "failed"
+ enum:
+ - "failed"
+ /tasks/{taskgroupID}:
+ put:
+ security:
+ - API_TOKEN: []
+ tags:
+ - task
+ summary: creates a new task
+ description: creates tasks
+ parameters:
+ - name: taskgroupID
+ in: path
+ description: internal id of taskgroup
+ required: true
+ schema:
+ type: number
+ example: 1
+ requestBody:
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/TaskFieldInfo'
+ responses:
+ 200:
+ description: Anfrage erfolgreich
+ content:
+ 'application/json':
+ schema:
+ type: object
+ $ref: '#/components/schemas/TaskEntityInfo'
+ 403:
+ description: No permission
+ content:
+ 'application/json':
+ schema:
+ type: object
+ required:
+ - status
+ properties:
+ status:
+ type: string
+ description: Status
+ example: "failed"
+ enum:
+ - "failed"
+ 404:
+ description: Taskgroup does not exist
+ content:
+ 'application/json':
+ schema:
+ type: object
+ required:
+ - status
+ properties:
+ status:
+ type: string
+ description: Status
+ example: "failed"
+ enum:
+ - "failed"
+ 409:
+ description: Task already exist
+ content:
+ 'application/json':
+ schema:
+ type: object
+ required:
+ - status
+ properties:
+ status:
+ type: string
+ description: Status
+ example: "failed"
+ enum:
+ - "failed"
+
components:
securitySchemes:
API_TOKEN:
@@ -1051,4 +1192,63 @@ components:
type: number
description: internal id of parent Taskgroup
example: 1
-
\ No newline at end of file
+ TaskEntityInfo:
+ required:
+ - taskID
+ - taskName
+ - eta
+ - startDate
+ - deadline
+ - overdue
+ additionalProperties: false
+ properties:
+ taskID:
+ type: number
+ description: internal id of task
+ example: 1
+ taskName:
+ type: string
+ description: name of task
+ example: Vorlesung schauen
+ eta:
+ type: number
+ description: expected time to finish task
+ example: 10
+ minimum: 0
+ startDate:
+ type: string
+ format: date
+ description: date from which the task can be started
+ deadline:
+ type: string
+ format: date
+ description: date until the task has to be finished
+ overdue:
+ type: boolean
+ description: determines whether the task is overdue
+ example: True
+ TaskFieldInfo:
+ required:
+ - taskName
+ - eta
+ - startDate
+ - deadline
+ additionalProperties: false
+ properties:
+ taskName:
+ type: string
+ description: name of task
+ example: Vorlesung schauen
+ eta:
+ type: number
+ description: expected time to finish task
+ example: 10
+ minimum: 0
+ startDate:
+ type: string
+ format: date
+ description: date from which the task can be started
+ deadline:
+ type: string
+ format: date
+ description: date until the task has to be finished
\ No newline at end of file