Merge pull request 'issue-10' (#17) from issue-10 into master
Reviewed-on: Sebastian/TimeManager#17
This commit is contained in:
commit
4cab32fae3
@ -10,3 +10,5 @@ npm install @openapitools/openapi-generator-cli -g
|
||||
```bash
|
||||
npx @openapitools/openapi-generator-cli generate -i openapi.yaml -g typescript-angular -o frontend/src/api/
|
||||
```
|
||||
|
||||
Notiz: Angular Calendar https://www.npmjs.com/package/angular-calendar
|
File diff suppressed because it is too large
Load Diff
@ -1,2 +0,0 @@
|
||||
#n:information_schema
|
||||
!<md> [null, 0, null, null, -2147483648, -2147483648]
|
@ -1,2 +0,0 @@
|
||||
#n:mysql
|
||||
!<md> [null, 0, null, null, -2147483648, -2147483648]
|
@ -1,2 +0,0 @@
|
||||
#n:performance_schema
|
||||
!<md> [null, 0, null, null, -2147483648, -2147483648]
|
@ -1,2 +0,0 @@
|
||||
#n:restservice
|
||||
!<md> [1695647618000, 0, null, null, -2147483648, -2147483648]
|
@ -9,4 +9,7 @@
|
||||
</option>
|
||||
</component>
|
||||
<component name="ProjectRootManager" version="2" languageLevel="JDK_17" default="true" project-jdk-name="17" project-jdk-type="JavaSDK" />
|
||||
<component name="ProjectType">
|
||||
<option name="id" value="jpab" />
|
||||
</component>
|
||||
</project>
|
@ -4,19 +4,46 @@
|
||||
<option name="autoReloadType" value="SELECTIVE" />
|
||||
</component>
|
||||
<component name="ChangeListManager">
|
||||
<list default="true" id="3a869f59-290a-4ab2-b036-a878ce801bc4" name="Changes" comment="Structure Taskgroups in Hierarchies">
|
||||
<list default="true" id="3a869f59-290a-4ab2-b036-a878ce801bc4" name="Changes" comment="Delete and clear Tasks (Frontend)">
|
||||
<change afterPath="$PROJECT_DIR$/src/main/java/core/api/models/timemanager/taskgroup/TaskgroupDetailInfo.java" afterDir="false" />
|
||||
<change afterPath="$PROJECT_DIR$/src/main/java/core/api/models/timemanager/taskgroup/TaskgroupShortInfo.java" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/.idea/workspace.xml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/workspace.xml" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/../frontend/src/app/taskgroups/taskgroup-creation/taskgroup-creation.component.ts" beforeDir="false" afterPath="$PROJECT_DIR$/../frontend/src/app/taskgroups/taskgroup-creation/taskgroup-creation.component.ts" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/src/main/java/core/api/controller/TaskgroupController.java" beforeDir="false" afterPath="$PROJECT_DIR$/src/main/java/core/api/controller/TaskgroupController.java" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/src/main/java/core/api/models/timemanager/taskgroup/TaskgroupEntityInfo.java" beforeDir="false" afterPath="$PROJECT_DIR$/src/main/java/core/api/models/timemanager/taskgroup/TaskgroupEntityInfo.java" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/src/main/java/core/entities/timemanager/Taskgroup.java" beforeDir="false" afterPath="$PROJECT_DIR$/src/main/java/core/entities/timemanager/Taskgroup.java" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/../frontend/src/api/.openapi-generator/FILES" beforeDir="false" afterPath="$PROJECT_DIR$/../frontend/src/api/.openapi-generator/FILES" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/../frontend/src/api/api/taskgroup.service.ts" beforeDir="false" afterPath="$PROJECT_DIR$/../frontend/src/api/api/taskgroup.service.ts" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/../frontend/src/api/model/models.ts" beforeDir="false" afterPath="$PROJECT_DIR$/../frontend/src/api/model/models.ts" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/../frontend/src/app/app.module.ts" beforeDir="false" afterPath="$PROJECT_DIR$/../frontend/src/app/app.module.ts" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/../frontend/src/app/taskgroups/taskgroup-dashboard/taskgroup-dashboard.component.css" beforeDir="false" afterPath="$PROJECT_DIR$/../frontend/src/app/taskgroups/taskgroup-dashboard/taskgroup-dashboard.component.css" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/../frontend/src/app/taskgroups/taskgroup-dashboard/taskgroup-dashboard.component.html" beforeDir="false" afterPath="$PROJECT_DIR$/../frontend/src/app/taskgroups/taskgroup-dashboard/taskgroup-dashboard.component.html" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/../frontend/src/app/taskgroups/taskgroup-dashboard/taskgroup-dashboard.component.ts" beforeDir="false" afterPath="$PROJECT_DIR$/../frontend/src/app/taskgroups/taskgroup-dashboard/taskgroup-dashboard.component.ts" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/../openapi.yaml" beforeDir="false" afterPath="$PROJECT_DIR$/../openapi.yaml" afterDir="false" />
|
||||
</list>
|
||||
<option name="SHOW_DIALOG" value="false" />
|
||||
<option name="HIGHLIGHT_CONFLICTS" value="true" />
|
||||
<option name="HIGHLIGHT_NON_ACTIVE_CHANGELIST" value="false" />
|
||||
<option name="LAST_RESOLUTION" value="IGNORE" />
|
||||
</component>
|
||||
<component name="FileTemplateManagerImpl">
|
||||
<option name="RECENT_TEMPLATES">
|
||||
<list>
|
||||
<option value="Interface" />
|
||||
<option value="Class" />
|
||||
</list>
|
||||
</option>
|
||||
</component>
|
||||
<component name="Git.Settings">
|
||||
<option name="RECENT_BRANCH_BY_REPOSITORY">
|
||||
<map>
|
||||
<entry key="$PROJECT_DIR$/.." value="master" />
|
||||
</map>
|
||||
</option>
|
||||
<option name="RECENT_GIT_ROOT_PATH" value="$PROJECT_DIR$/.." />
|
||||
</component>
|
||||
<component name="JpbToolWindowState">
|
||||
<option name="isToolWindowVisible" value="false" />
|
||||
</component>
|
||||
<component name="ProjectColorInfo">{
|
||||
"customColor": "",
|
||||
"associatedIndex": 6
|
||||
@ -35,11 +62,14 @@
|
||||
"RunOnceActivity.OpenProjectViewOnStart": "true",
|
||||
"RunOnceActivity.ShowReadmeOnStart": "true",
|
||||
"WebServerToolWindowFactoryState": "false",
|
||||
"git-widget-placeholder": "issue-7",
|
||||
"git-widget-placeholder": "issue-11-angular-update",
|
||||
"last_directory_selection": "D:/Programmierprojekte/TimeManager/backend/src/main/java/core/api/models/timemanager",
|
||||
"last_opened_file_path": "D:/Programmierprojekte/Dicewars/client",
|
||||
"node.js.detected.package.eslint": "true",
|
||||
"node.js.detected.package.tslint": "true",
|
||||
"node.js.selected.package.eslint": "(autodetect)",
|
||||
"node.js.selected.package.tslint": "(autodetect)",
|
||||
"settings.editor.selected.configurable": "preferences.lookFeel",
|
||||
"vue.rearranger.settings.migration": "true"
|
||||
},
|
||||
"keyToStringList": {
|
||||
@ -67,6 +97,12 @@
|
||||
<updated>1695647243767</updated>
|
||||
<workItem from="1695647249321" duration="397000" />
|
||||
<workItem from="1696183811713" duration="4994000" />
|
||||
<workItem from="1696399523081" duration="666000" />
|
||||
<workItem from="1696517800445" duration="3887000" />
|
||||
<workItem from="1696573678147" duration="111000" />
|
||||
<workItem from="1697923629354" duration="3164000" />
|
||||
<workItem from="1697958018921" duration="91000" />
|
||||
<workItem from="1697958118995" duration="5749000" />
|
||||
</task>
|
||||
<task id="LOCAL-00001" summary="Structure Taskgroups in Hierarchies">
|
||||
<option name="closed" value="true" />
|
||||
@ -76,7 +112,39 @@
|
||||
<option name="project" value="LOCAL" />
|
||||
<updated>1696188127467</updated>
|
||||
</task>
|
||||
<option name="localTasksCounter" value="2" />
|
||||
<task id="LOCAL-00002" summary="Datastructure for Tasks">
|
||||
<option name="closed" value="true" />
|
||||
<created>1696233406235</created>
|
||||
<option name="number" value="00002" />
|
||||
<option name="presentableId" value="LOCAL-00002" />
|
||||
<option name="project" value="LOCAL" />
|
||||
<updated>1696233406235</updated>
|
||||
</task>
|
||||
<task id="LOCAL-00003" summary="Implementing edit route for tasks">
|
||||
<option name="closed" value="true" />
|
||||
<created>1697929392755</created>
|
||||
<option name="number" value="00003" />
|
||||
<option name="presentableId" value="LOCAL-00003" />
|
||||
<option name="project" value="LOCAL" />
|
||||
<updated>1697929392755</updated>
|
||||
</task>
|
||||
<task id="LOCAL-00004" summary="Delete and clear Tasks">
|
||||
<option name="closed" value="true" />
|
||||
<created>1697962016013</created>
|
||||
<option name="number" value="00004" />
|
||||
<option name="presentableId" value="LOCAL-00004" />
|
||||
<option name="project" value="LOCAL" />
|
||||
<updated>1697962016013</updated>
|
||||
</task>
|
||||
<task id="LOCAL-00005" summary="Delete and clear Tasks (Frontend)">
|
||||
<option name="closed" value="true" />
|
||||
<created>1697962125518</created>
|
||||
<option name="number" value="00005" />
|
||||
<option name="presentableId" value="LOCAL-00005" />
|
||||
<option name="project" value="LOCAL" />
|
||||
<updated>1697962125518</updated>
|
||||
</task>
|
||||
<option name="localTasksCounter" value="6" />
|
||||
<servers />
|
||||
</component>
|
||||
<component name="TypeScriptGeneratedFilesManager">
|
||||
@ -84,7 +152,12 @@
|
||||
</component>
|
||||
<component name="VcsManagerConfiguration">
|
||||
<MESSAGE value="Structure Taskgroups in Hierarchies" />
|
||||
<option name="LAST_COMMIT_MESSAGE" value="Structure Taskgroups in Hierarchies" />
|
||||
<MESSAGE value="Update gitignore for idea folder" />
|
||||
<MESSAGE value="Datastructure for Tasks" />
|
||||
<MESSAGE value="Implementing edit route for tasks" />
|
||||
<MESSAGE value="Delete and clear Tasks" />
|
||||
<MESSAGE value="Delete and clear Tasks (Frontend)" />
|
||||
<option name="LAST_COMMIT_MESSAGE" value="Delete and clear Tasks (Frontend)" />
|
||||
</component>
|
||||
<component name="XDebuggerManager">
|
||||
<breakpoint-manager>
|
||||
|
@ -0,0 +1,99 @@
|
||||
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<Taskgroup> 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"));
|
||||
}
|
||||
|
||||
return ResponseEntity.ok(taskgroupPermissionResult.getResult().getTasks().stream().map(TaskEntityInfo::new));
|
||||
}
|
||||
|
||||
@PutMapping("/tasks/{taskgroupID}")
|
||||
public ResponseEntity<?> createTask(@PathVariable long taskgroupID, @RequestBody @Valid TaskFieldInfo taskFieldInfo) {
|
||||
PermissionResult<Taskgroup> 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<Task> 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()));
|
||||
}
|
||||
}
|
||||
|
||||
@PostMapping("/tasks/{taskID}")
|
||||
public ResponseEntity<?> editTask(@PathVariable long taskID, @RequestBody @Valid TaskFieldInfo taskFieldInfo) {
|
||||
PermissionResult<Task> taskPermissionResult = taskService.getTaskPermissions(taskID, SecurityContextHolder.getContext().getAuthentication().getName());
|
||||
if (!taskPermissionResult.isHasPermissions()) {
|
||||
return ResponseEntity.status(403).body(new SimpleStatusResponse("failed"));
|
||||
}
|
||||
|
||||
if (taskPermissionResult.getExitCode() == ServiceExitCode.MISSING_ENTITY) {
|
||||
return ResponseEntity.status(404).body(new SimpleStatusResponse("failed"));
|
||||
}
|
||||
|
||||
if(taskFieldInfo.getStartDate().isAfter(taskFieldInfo.getDeadline())) {
|
||||
return ResponseEntity.status(400).body(new SimpleStatusResponse("failed"));
|
||||
}
|
||||
|
||||
ServiceResult<Task> editorResult = taskService.editTask(taskPermissionResult.getResult(), taskFieldInfo);
|
||||
if (editorResult.getExitCode() == ServiceExitCode.OK) {
|
||||
return ResponseEntity.ok(new SimpleStatusResponse("success"));
|
||||
} else {
|
||||
return ResponseEntity.status(409).body(new SimpleStatusResponse("failed"));
|
||||
}
|
||||
}
|
||||
|
||||
@DeleteMapping("/tasks/{taskID}")
|
||||
public ResponseEntity<?> deleteTask(@PathVariable long taskID) {
|
||||
PermissionResult<Task> taskPermissionResult = taskService.getTaskPermissions(taskID, SecurityContextHolder.getContext().getAuthentication().getName());
|
||||
if (!taskPermissionResult.isHasPermissions()) {
|
||||
return ResponseEntity.status(403).body(new SimpleStatusResponse("failed"));
|
||||
}
|
||||
|
||||
if (taskPermissionResult.getExitCode() == ServiceExitCode.MISSING_ENTITY) {
|
||||
return ResponseEntity.status(404).body(new SimpleStatusResponse("failed"));
|
||||
}
|
||||
|
||||
taskService.deleteTask(taskPermissionResult.getResult());
|
||||
return ResponseEntity.ok(new SimpleStatusResponse("success"));
|
||||
}
|
||||
}
|
@ -1,16 +1,13 @@
|
||||
package core.api.controller;
|
||||
|
||||
import core.api.models.auth.SimpleStatusResponse;
|
||||
import core.api.models.timemanager.taskgroup.TaskgroupDetailInfo;
|
||||
import core.api.models.timemanager.taskgroup.TaskgroupEntityInfo;
|
||||
import core.api.models.timemanager.taskgroup.TaskgroupFieldInfo;
|
||||
import core.entities.timemanager.Taskgroup;
|
||||
import core.services.PermissionResult;
|
||||
import core.services.ServiceExitCode;
|
||||
import core.services.ServiceResult;
|
||||
import core.services.TaskgroupService;
|
||||
import core.services.*;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.scheduling.config.Task;
|
||||
import org.springframework.security.core.context.SecurityContextHolder;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
@ -24,9 +21,11 @@ import java.util.Set;
|
||||
public class TaskgroupController {
|
||||
|
||||
private final TaskgroupService taskgroupService;
|
||||
private final TaskService taskService;
|
||||
|
||||
public TaskgroupController(@Autowired TaskgroupService taskgroupService) {
|
||||
public TaskgroupController(@Autowired TaskgroupService taskgroupService, @Autowired TaskService taskService) {
|
||||
this.taskgroupService = taskgroupService;
|
||||
this.taskService = taskService;
|
||||
}
|
||||
|
||||
@PutMapping("/taskgroups")
|
||||
@ -92,7 +91,21 @@ public class TaskgroupController {
|
||||
return ResponseEntity.status(404).body(new SimpleStatusResponse("failed"));
|
||||
}
|
||||
|
||||
Set<Taskgroup> children = taskgroupPermissionResult.getResult().getChildren();
|
||||
return ResponseEntity.ok(children.stream().map(TaskgroupEntityInfo::new));
|
||||
return ResponseEntity.ok(new TaskgroupDetailInfo(taskgroupPermissionResult.getResult()));
|
||||
}
|
||||
|
||||
@DeleteMapping("/taskgroups/{taskgroupID}/clear")
|
||||
public ResponseEntity<?> clearTasks(@PathVariable long taskgroupID) {
|
||||
PermissionResult<Taskgroup> 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"));
|
||||
}
|
||||
|
||||
taskService.clearTasks(taskgroupPermissionResult.getResult());
|
||||
return ResponseEntity.ok(new SimpleStatusResponse("success"));
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,45 @@
|
||||
package core.api.models.timemanager.taskgroup;
|
||||
|
||||
import core.entities.timemanager.Taskgroup;
|
||||
import org.springframework.scheduling.config.Task;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class TaskgroupDetailInfo {
|
||||
|
||||
private List<TaskgroupEntityInfo> children;
|
||||
private List<TaskgroupEntityInfo> ancestors;
|
||||
private TaskgroupEntityInfo taskgroupInfo;
|
||||
|
||||
public TaskgroupDetailInfo(Taskgroup taskgroup) {
|
||||
this.children = taskgroup.getChildren().stream().map(TaskgroupEntityInfo::new).toList();
|
||||
List<Taskgroup> ancestorList = Taskgroup.getAncestorList(taskgroup);
|
||||
this.ancestors = ancestorList.stream().map(TaskgroupEntityInfo::new).toList();
|
||||
this.taskgroupInfo = new TaskgroupEntityInfo(taskgroup);
|
||||
}
|
||||
|
||||
public List<TaskgroupEntityInfo> getChildren() {
|
||||
return children;
|
||||
}
|
||||
|
||||
public void setChildren(List<TaskgroupEntityInfo> children) {
|
||||
this.children = children;
|
||||
}
|
||||
|
||||
public List<TaskgroupEntityInfo> getAncestors() {
|
||||
return ancestors;
|
||||
}
|
||||
|
||||
public void setAncestors(List<TaskgroupEntityInfo> ancestors) {
|
||||
this.ancestors = ancestors;
|
||||
}
|
||||
|
||||
public TaskgroupEntityInfo getTaskgroupInfo() {
|
||||
return taskgroupInfo;
|
||||
}
|
||||
|
||||
public void setTaskgroupInfo(TaskgroupEntityInfo taskgroupInfo) {
|
||||
this.taskgroupInfo = taskgroupInfo;
|
||||
}
|
||||
}
|
@ -7,17 +7,9 @@ public class TaskgroupEntityInfo {
|
||||
private long taskgroupID;
|
||||
private String taskgroupName;
|
||||
|
||||
private TaskgroupEntityInfo parentTaskgroup;
|
||||
|
||||
public TaskgroupEntityInfo(Taskgroup taskgroup) {
|
||||
this.taskgroupID = taskgroup.getTaskgroupID();
|
||||
this.taskgroupName = taskgroup.getTaskgroupName();
|
||||
|
||||
if(taskgroup.getParent() == null) {
|
||||
this.parentTaskgroup = null;
|
||||
} else {
|
||||
this.parentTaskgroup = new TaskgroupEntityInfo(taskgroup.getParent());
|
||||
}
|
||||
}
|
||||
|
||||
public long getTaskgroupID() {
|
||||
@ -35,12 +27,4 @@ public class TaskgroupEntityInfo {
|
||||
public void setTaskgroupName(String taskgroupName) {
|
||||
this.taskgroupName = taskgroupName;
|
||||
}
|
||||
|
||||
public TaskgroupEntityInfo getParentTaskgroup() {
|
||||
return parentTaskgroup;
|
||||
}
|
||||
|
||||
public void setParentTaskgroup(TaskgroupEntityInfo parentTaskgroup) {
|
||||
this.parentTaskgroup = parentTaskgroup;
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,7 @@
|
||||
package core.api.models.timemanager.taskgroup;
|
||||
|
||||
public class TaskgroupShortInfo {
|
||||
|
||||
private long taskgroupID;
|
||||
private String taskgroupName;
|
||||
}
|
@ -0,0 +1,88 @@
|
||||
package core.api.models.timemanager.tasks;
|
||||
|
||||
import core.api.models.timemanager.taskgroup.TaskgroupEntityInfo;
|
||||
import core.entities.timemanager.Task;
|
||||
|
||||
import java.time.LocalDate;
|
||||
|
||||
public class TaskEntityInfo {
|
||||
|
||||
private long taskID;
|
||||
private String taskName;
|
||||
|
||||
private int eta;
|
||||
|
||||
private LocalDate startDate;
|
||||
|
||||
private LocalDate deadline;
|
||||
|
||||
private boolean overdue;
|
||||
|
||||
private boolean finished;
|
||||
|
||||
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());
|
||||
this.finished = task.isFinished();
|
||||
}
|
||||
|
||||
public long getTaskID() {
|
||||
return taskID;
|
||||
}
|
||||
|
||||
public void setTaskID(long taskID) {
|
||||
this.taskID = taskID;
|
||||
}
|
||||
|
||||
public String getTaskName() {
|
||||
return taskName;
|
||||
}
|
||||
|
||||
public void setTaskName(String taskName) {
|
||||
this.taskName = taskName;
|
||||
}
|
||||
|
||||
public int getEta() {
|
||||
return eta;
|
||||
}
|
||||
|
||||
public void setEta(int eta) {
|
||||
this.eta = eta;
|
||||
}
|
||||
|
||||
public LocalDate getStartDate() {
|
||||
return startDate;
|
||||
}
|
||||
|
||||
public void setStartDate(LocalDate startDate) {
|
||||
this.startDate = startDate;
|
||||
}
|
||||
|
||||
public LocalDate getDeadline() {
|
||||
return deadline;
|
||||
}
|
||||
|
||||
public void setDeadline(LocalDate deadline) {
|
||||
this.deadline = deadline;
|
||||
}
|
||||
|
||||
public boolean isOverdue() {
|
||||
return overdue;
|
||||
}
|
||||
|
||||
public void setOverdue(boolean overdue) {
|
||||
this.overdue = overdue;
|
||||
}
|
||||
|
||||
public boolean isFinished() {
|
||||
return finished;
|
||||
}
|
||||
|
||||
public void setFinished(boolean finished) {
|
||||
this.finished = finished;
|
||||
}
|
||||
}
|
@ -0,0 +1,48 @@
|
||||
package core.api.models.timemanager.tasks;
|
||||
|
||||
import org.hibernate.validator.constraints.Length;
|
||||
|
||||
import javax.validation.constraints.NotBlank;
|
||||
import java.time.LocalDate;
|
||||
|
||||
public class TaskFieldInfo {
|
||||
|
||||
@NotBlank
|
||||
@Length(max = 255)
|
||||
private String taskName;
|
||||
private int eta;
|
||||
private LocalDate startDate;
|
||||
private LocalDate deadline;
|
||||
|
||||
public String getTaskName() {
|
||||
return taskName;
|
||||
}
|
||||
|
||||
public void setTaskName(String taskName) {
|
||||
this.taskName = taskName;
|
||||
}
|
||||
|
||||
public int getEta() {
|
||||
return eta;
|
||||
}
|
||||
|
||||
public void setEta(int eta) {
|
||||
this.eta = eta;
|
||||
}
|
||||
|
||||
public LocalDate getStartDate() {
|
||||
return startDate;
|
||||
}
|
||||
|
||||
public void setStartDate(LocalDate startDate) {
|
||||
this.startDate = startDate;
|
||||
}
|
||||
|
||||
public LocalDate getDeadline() {
|
||||
return deadline;
|
||||
}
|
||||
|
||||
public void setDeadline(LocalDate deadline) {
|
||||
this.deadline = deadline;
|
||||
}
|
||||
}
|
108
backend/src/main/java/core/entities/timemanager/Task.java
Normal file
108
backend/src/main/java/core/entities/timemanager/Task.java
Normal file
@ -0,0 +1,108 @@
|
||||
package core.entities.timemanager;
|
||||
|
||||
import javax.persistence.*;
|
||||
import java.time.LocalDate;
|
||||
import java.util.Objects;
|
||||
|
||||
@Entity
|
||||
@Table(name = "tasks")
|
||||
public class Task {
|
||||
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.AUTO)
|
||||
private long taskID;
|
||||
|
||||
@ManyToOne
|
||||
@JoinColumn(name = "taskgroup_id")
|
||||
private Taskgroup taskgroup;
|
||||
private String taskName;
|
||||
|
||||
private LocalDate startDate;
|
||||
|
||||
private LocalDate deadline;
|
||||
|
||||
private int eta;
|
||||
|
||||
private boolean finished;
|
||||
|
||||
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;
|
||||
this.finished = false;
|
||||
}
|
||||
|
||||
public Task() {
|
||||
}
|
||||
|
||||
public long getTaskID() {
|
||||
return taskID;
|
||||
}
|
||||
|
||||
public Taskgroup getTaskgroup() {
|
||||
return taskgroup;
|
||||
}
|
||||
|
||||
public void setTaskgroup(Taskgroup taskgroup) {
|
||||
this.taskgroup = taskgroup;
|
||||
}
|
||||
|
||||
public String getTaskName() {
|
||||
return taskName;
|
||||
}
|
||||
|
||||
public void setTaskName(String taskName) {
|
||||
this.taskName = taskName;
|
||||
}
|
||||
|
||||
public LocalDate getStartDate() {
|
||||
return startDate;
|
||||
}
|
||||
|
||||
public void setStartDate(LocalDate startDate) {
|
||||
this.startDate = startDate;
|
||||
}
|
||||
|
||||
public LocalDate getDeadline() {
|
||||
return deadline;
|
||||
}
|
||||
|
||||
public void setDeadline(LocalDate deadline) {
|
||||
this.deadline = deadline;
|
||||
}
|
||||
|
||||
public int getEta() {
|
||||
return eta;
|
||||
}
|
||||
|
||||
public void setEta(int eta) {
|
||||
this.eta = eta;
|
||||
}
|
||||
|
||||
public void finish() {
|
||||
this.finished = true;
|
||||
}
|
||||
|
||||
public boolean isFinished() {
|
||||
return finished;
|
||||
}
|
||||
|
||||
public void setFinished(boolean finished) {
|
||||
this.finished = finished;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
Task task = (Task) o;
|
||||
return taskID == task.taskID;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(taskID);
|
||||
}
|
||||
}
|
@ -4,7 +4,7 @@ import core.entities.User;
|
||||
|
||||
import javax.persistence.*;
|
||||
import javax.validation.constraints.NotBlank;
|
||||
import java.util.Set;
|
||||
import java.util.*;
|
||||
|
||||
@Entity
|
||||
@Table(name= "taskgroups")
|
||||
@ -29,6 +29,9 @@ public class Taskgroup {
|
||||
@JoinColumn(name = "parent_id")
|
||||
private Taskgroup parent;
|
||||
|
||||
@OneToMany(mappedBy = "taskgroup", cascade = CascadeType.ALL, fetch = FetchType.EAGER)
|
||||
private Set<Task> tasks;
|
||||
|
||||
public Taskgroup(String taskgroupName, User user) {
|
||||
this.taskgroupName = taskgroupName;
|
||||
this.user = user;
|
||||
@ -76,4 +79,22 @@ public class Taskgroup {
|
||||
public void setParent(Taskgroup parent) {
|
||||
this.parent = parent;
|
||||
}
|
||||
|
||||
public Set<Task> getTasks() {
|
||||
return tasks;
|
||||
}
|
||||
|
||||
public void setTasks(Set<Task> tasks) {
|
||||
this.tasks = tasks;
|
||||
}
|
||||
|
||||
public static List<Taskgroup> getAncestorList(Taskgroup taskgroup) {
|
||||
List<Taskgroup> ancestors = new ArrayList<>();
|
||||
Taskgroup currentTaskgroup = taskgroup;
|
||||
while(currentTaskgroup.parent != null) {
|
||||
ancestors.add(currentTaskgroup.parent);
|
||||
currentTaskgroup = currentTaskgroup.parent;
|
||||
}
|
||||
return ancestors;
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,24 @@
|
||||
package core.repositories.timemanager;
|
||||
|
||||
import core.entities.timemanager.Task;
|
||||
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 TaskRepository extends CrudRepository<Task, Long> {
|
||||
|
||||
@Transactional
|
||||
@Modifying
|
||||
@Query(value = "DELETE FROM Task t WHERE t.taskgroup = ?1")
|
||||
void deleteAllByTaskgroup(Taskgroup taskgroup);
|
||||
|
||||
@Transactional
|
||||
@Modifying
|
||||
@Query(value = "DELETE FROM Task t WHERE t.taskID = ?1")
|
||||
void deleteByTaskID(long taskID);
|
||||
}
|
76
backend/src/main/java/core/services/TaskService.java
Normal file
76
backend/src/main/java/core/services/TaskService.java
Normal file
@ -0,0 +1,76 @@
|
||||
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 core.repositories.timemanager.TaskgroupRepository;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
@Service
|
||||
public class TaskService {
|
||||
|
||||
private final TaskRepository taskRepository;
|
||||
private final TaskgroupRepository taskgroupRepository;
|
||||
|
||||
public TaskService(@Autowired TaskRepository taskRepository,
|
||||
TaskgroupRepository taskgroupRepository) {
|
||||
this.taskRepository = taskRepository;
|
||||
this.taskgroupRepository = taskgroupRepository;
|
||||
}
|
||||
|
||||
public ServiceResult<Task> 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<Task> tasks, String name) {
|
||||
for(Task task : tasks) {
|
||||
if(task.getTaskName().equals(name)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public PermissionResult<Task> getTaskPermissions(long taskID, String name) {
|
||||
Optional<Task> task = taskRepository.findById(taskID);
|
||||
return task.map(value -> new PermissionResult<>(value, value.getTaskgroup().getUser().getUsername().equals(name))).orElseGet(() ->
|
||||
new PermissionResult<>(ServiceExitCode.MISSING_ENTITY));
|
||||
}
|
||||
|
||||
public ServiceResult<Task> editTask(Task task, TaskFieldInfo taskFieldInfo) {
|
||||
if(!task.getTaskName().equals(taskFieldInfo.getTaskName()) && !existTaskByName(task.getTaskgroup().getTasks(), taskFieldInfo.getTaskName())) {
|
||||
task.setTaskName(taskFieldInfo.getTaskName());
|
||||
|
||||
} else if(!task.getTaskName().equals(taskFieldInfo.getTaskName()) && existTaskByName(task.getTaskgroup().getTasks(), taskFieldInfo.getTaskName())) {
|
||||
return new ServiceResult<>(ServiceExitCode.ENTITY_ALREADY_EXIST);
|
||||
}
|
||||
task.setEta(taskFieldInfo.getEta());
|
||||
task.setStartDate(taskFieldInfo.getStartDate());
|
||||
task.setDeadline(taskFieldInfo.getDeadline());
|
||||
taskRepository.save(task);
|
||||
return new ServiceResult<>(task);
|
||||
}
|
||||
|
||||
public void deleteTask(Task task) {
|
||||
taskRepository.deleteByTaskID(task.getTaskID());
|
||||
}
|
||||
|
||||
public void clearTasks(Taskgroup taskgroup) {
|
||||
taskRepository.deleteAllByTaskgroup(taskgroup);
|
||||
}
|
||||
}
|
@ -1,16 +0,0 @@
|
||||
# This file is used by the build system to adjust CSS and JS output to support the specified browsers below.
|
||||
# For additional information regarding the format and rule options, please see:
|
||||
# https://github.com/browserslist/browserslist#queries
|
||||
|
||||
# For the full list of supported browsers by the Angular framework, please see:
|
||||
# https://angular.io/guide/browser-support
|
||||
|
||||
# You can see what browsers were selected by your queries by running:
|
||||
# npx browserslist
|
||||
|
||||
last 1 Chrome version
|
||||
last 1 Firefox version
|
||||
last 2 Edge major versions
|
||||
last 2 Safari major versions
|
||||
last 2 iOS major versions
|
||||
Firefox ESR
|
@ -103,6 +103,5 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"defaultProject": "frontend"
|
||||
}
|
||||
}
|
||||
|
18152
frontend/package-lock.json
generated
18152
frontend/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@ -10,24 +10,28 @@
|
||||
},
|
||||
"private": true,
|
||||
"dependencies": {
|
||||
"@angular/animations": "~13.2.0",
|
||||
"@angular/cdk": "^13.2.2",
|
||||
"@angular/common": "~13.2.0",
|
||||
"@angular/compiler": "~13.2.0",
|
||||
"@angular/core": "~13.2.0",
|
||||
"@angular/forms": "~13.2.0",
|
||||
"@angular/material": "^13.2.2",
|
||||
"@angular/platform-browser": "~13.2.0",
|
||||
"@angular/platform-browser-dynamic": "~13.2.0",
|
||||
"@angular/router": "~13.2.0",
|
||||
"@angular-material-components/datetime-picker": "^16.0.1",
|
||||
"@angular-material-components/moment-adapter": "^16.0.1",
|
||||
"@angular/animations": "^16.2.7",
|
||||
"@angular/cdk": "^16.2.6",
|
||||
"@angular/common": "^16.2.7",
|
||||
"@angular/compiler": "^16.2.7",
|
||||
"@angular/core": "^16.2.7",
|
||||
"@angular/forms": "^16.2.7",
|
||||
"@angular/material": "^16.2.6",
|
||||
"@angular/material-moment-adapter": "^16.2.7",
|
||||
"@angular/platform-browser": "^16.2.7",
|
||||
"@angular/platform-browser-dynamic": "^16.2.7",
|
||||
"@angular/router": "^16.2.7",
|
||||
"moment": "^2.29.4",
|
||||
"rxjs": "~7.5.0",
|
||||
"tslib": "^2.3.0",
|
||||
"zone.js": "~0.11.4"
|
||||
"zone.js": "~0.13.3"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@angular-devkit/build-angular": "~13.2.2",
|
||||
"@angular/cli": "~13.2.2",
|
||||
"@angular/compiler-cli": "~13.2.0",
|
||||
"@angular-devkit/build-angular": "^16.2.4",
|
||||
"@angular/cli": "^16.2.4",
|
||||
"@angular/compiler-cli": "^16.2.7",
|
||||
"@types/jasmine": "~3.10.0",
|
||||
"@types/node": "^12.11.1",
|
||||
"jasmine-core": "~4.0.0",
|
||||
@ -36,6 +40,6 @@
|
||||
"karma-coverage": "~2.1.0",
|
||||
"karma-jasmine": "~4.0.0",
|
||||
"karma-jasmine-html-reporter": "~1.7.0",
|
||||
"typescript": "~4.5.2"
|
||||
"typescript": "~5.1.6"
|
||||
}
|
||||
}
|
@ -5,6 +5,7 @@ api/account.service.ts
|
||||
api/api.ts
|
||||
api/login.service.ts
|
||||
api/properties.service.ts
|
||||
api/task.service.ts
|
||||
api/taskgroup.service.ts
|
||||
api/users.service.ts
|
||||
configuration.ts
|
||||
@ -25,6 +26,10 @@ model/propertiesInfo.ts
|
||||
model/propertyInfo.ts
|
||||
model/propertyUpdateRequest.ts
|
||||
model/signUpRequest.ts
|
||||
model/simpleStatusResponse.ts
|
||||
model/taskEntityInfo.ts
|
||||
model/taskFieldInfo.ts
|
||||
model/taskgroupDetailInfo.ts
|
||||
model/taskgroupEntityInfo.ts
|
||||
model/taskgroupFieldInfo.ts
|
||||
model/userAddInfo.ts
|
||||
|
@ -5,6 +5,7 @@ import { HttpClient } from '@angular/common/http';
|
||||
import { AccountService } from './api/account.service';
|
||||
import { LoginService } from './api/login.service';
|
||||
import { PropertiesService } from './api/properties.service';
|
||||
import { TaskService } from './api/task.service';
|
||||
import { TaskgroupService } from './api/taskgroup.service';
|
||||
import { UsersService } from './api/users.service';
|
||||
|
||||
|
@ -4,8 +4,10 @@ export * from './login.service';
|
||||
import { LoginService } from './login.service';
|
||||
export * from './properties.service';
|
||||
import { PropertiesService } from './properties.service';
|
||||
export * from './task.service';
|
||||
import { TaskService } from './task.service';
|
||||
export * from './taskgroup.service';
|
||||
import { TaskgroupService } from './taskgroup.service';
|
||||
export * from './users.service';
|
||||
import { UsersService } from './users.service';
|
||||
export const APIS = [AccountService, LoginService, PropertiesService, TaskgroupService, UsersService];
|
||||
export const APIS = [AccountService, LoginService, PropertiesService, TaskService, TaskgroupService, UsersService];
|
||||
|
363
frontend/src/api/api/task.service.ts
Normal file
363
frontend/src/api/api/task.service.ts
Normal file
@ -0,0 +1,363 @@
|
||||
/**
|
||||
* 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 { InlineResponse403 } from '../model/models';
|
||||
import { SimpleStatusResponse } from '../model/models';
|
||||
import { TaskEntityInfo } from '../model/models';
|
||||
import { TaskFieldInfo } from '../model/models';
|
||||
|
||||
import { BASE_PATH, COLLECTION_FORMATS } from '../variables';
|
||||
import { Configuration } from '../configuration';
|
||||
|
||||
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root'
|
||||
})
|
||||
export class TaskService {
|
||||
|
||||
protected basePath = 'http://localhost:8080/api';
|
||||
public defaultHeaders = new HttpHeaders();
|
||||
public configuration = new Configuration();
|
||||
public encoder: HttpParameterCodec;
|
||||
|
||||
constructor(protected httpClient: HttpClient, @Optional()@Inject(BASE_PATH) basePath: string, @Optional() configuration: Configuration) {
|
||||
if (configuration) {
|
||||
this.configuration = configuration;
|
||||
}
|
||||
if (typeof this.configuration.basePath !== 'string') {
|
||||
if (typeof basePath !== 'string') {
|
||||
basePath = this.basePath;
|
||||
}
|
||||
this.configuration.basePath = basePath;
|
||||
}
|
||||
this.encoder = this.configuration.encoder || new CustomHttpParameterCodec();
|
||||
}
|
||||
|
||||
|
||||
private addToHttpParams(httpParams: HttpParams, value: any, key?: string): HttpParams {
|
||||
if (typeof value === "object" && value instanceof Date === false) {
|
||||
httpParams = this.addToHttpParamsRecursive(httpParams, value);
|
||||
} else {
|
||||
httpParams = this.addToHttpParamsRecursive(httpParams, value, key);
|
||||
}
|
||||
return httpParams;
|
||||
}
|
||||
|
||||
private addToHttpParamsRecursive(httpParams: HttpParams, value?: any, key?: string): HttpParams {
|
||||
if (value == null) {
|
||||
return httpParams;
|
||||
}
|
||||
|
||||
if (typeof value === "object") {
|
||||
if (Array.isArray(value)) {
|
||||
(value as any[]).forEach( elem => httpParams = this.addToHttpParamsRecursive(httpParams, elem, key));
|
||||
} else if (value instanceof Date) {
|
||||
if (key != null) {
|
||||
httpParams = httpParams.append(key,
|
||||
(value as Date).toISOString().substr(0, 10));
|
||||
} else {
|
||||
throw Error("key may not be null if value is Date");
|
||||
}
|
||||
} else {
|
||||
Object.keys(value).forEach( k => httpParams = this.addToHttpParamsRecursive(
|
||||
httpParams, value[k], key != null ? `${key}.${k}` : k));
|
||||
}
|
||||
} else if (key != null) {
|
||||
httpParams = httpParams.append(key, value);
|
||||
} else {
|
||||
throw Error("key may not be null if value is not object or array");
|
||||
}
|
||||
return httpParams;
|
||||
}
|
||||
|
||||
/**
|
||||
* edits an existing task
|
||||
* edits an existing task
|
||||
* @param taskID internal id of task
|
||||
* @param taskFieldInfo
|
||||
* @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 tasksTaskIDDelete(taskID: number, taskFieldInfo?: TaskFieldInfo, observe?: 'body', reportProgress?: boolean, options?: {httpHeaderAccept?: 'application/json', context?: HttpContext}): Observable<SimpleStatusResponse>;
|
||||
public tasksTaskIDDelete(taskID: number, taskFieldInfo?: TaskFieldInfo, observe?: 'response', reportProgress?: boolean, options?: {httpHeaderAccept?: 'application/json', context?: HttpContext}): Observable<HttpResponse<SimpleStatusResponse>>;
|
||||
public tasksTaskIDDelete(taskID: number, taskFieldInfo?: TaskFieldInfo, observe?: 'events', reportProgress?: boolean, options?: {httpHeaderAccept?: 'application/json', context?: HttpContext}): Observable<HttpEvent<SimpleStatusResponse>>;
|
||||
public tasksTaskIDDelete(taskID: number, taskFieldInfo?: TaskFieldInfo, 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 tasksTaskIDDelete.');
|
||||
}
|
||||
|
||||
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.delete<SimpleStatusResponse>(`${this.configuration.basePath}/tasks/${encodeURIComponent(String(taskID))}`,
|
||||
{
|
||||
context: localVarHttpContext,
|
||||
responseType: <any>responseType_,
|
||||
withCredentials: this.configuration.withCredentials,
|
||||
headers: localVarHeaders,
|
||||
observe: observe,
|
||||
reportProgress: reportProgress
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* edits an existing task
|
||||
* edits an existing task
|
||||
* @param taskID internal id of task
|
||||
* @param taskFieldInfo
|
||||
* @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 tasksTaskIDPost(taskID: number, taskFieldInfo?: TaskFieldInfo, observe?: 'body', reportProgress?: boolean, options?: {httpHeaderAccept?: 'application/json', context?: HttpContext}): Observable<TaskEntityInfo>;
|
||||
public tasksTaskIDPost(taskID: number, taskFieldInfo?: TaskFieldInfo, observe?: 'response', reportProgress?: boolean, options?: {httpHeaderAccept?: 'application/json', context?: HttpContext}): Observable<HttpResponse<TaskEntityInfo>>;
|
||||
public tasksTaskIDPost(taskID: number, taskFieldInfo?: TaskFieldInfo, observe?: 'events', reportProgress?: boolean, options?: {httpHeaderAccept?: 'application/json', context?: HttpContext}): Observable<HttpEvent<TaskEntityInfo>>;
|
||||
public tasksTaskIDPost(taskID: number, taskFieldInfo?: TaskFieldInfo, 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 tasksTaskIDPost.');
|
||||
}
|
||||
|
||||
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<TaskEntityInfo>(`${this.configuration.basePath}/tasks/${encodeURIComponent(String(taskID))}`,
|
||||
taskFieldInfo,
|
||||
{
|
||||
context: localVarHttpContext,
|
||||
responseType: <any>responseType_,
|
||||
withCredentials: this.configuration.withCredentials,
|
||||
headers: localVarHeaders,
|
||||
observe: observe,
|
||||
reportProgress: reportProgress
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* creates a new task
|
||||
* creates tasks
|
||||
* @param taskgroupID internal id of taskgroup
|
||||
* @param taskFieldInfo
|
||||
* @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 tasksTaskgroupIDPut(taskgroupID: number, taskFieldInfo?: TaskFieldInfo, observe?: 'body', reportProgress?: boolean, options?: {httpHeaderAccept?: 'application/json', context?: HttpContext}): Observable<TaskEntityInfo>;
|
||||
public tasksTaskgroupIDPut(taskgroupID: number, taskFieldInfo?: TaskFieldInfo, observe?: 'response', reportProgress?: boolean, options?: {httpHeaderAccept?: 'application/json', context?: HttpContext}): Observable<HttpResponse<TaskEntityInfo>>;
|
||||
public tasksTaskgroupIDPut(taskgroupID: number, taskFieldInfo?: TaskFieldInfo, observe?: 'events', reportProgress?: boolean, options?: {httpHeaderAccept?: 'application/json', context?: HttpContext}): Observable<HttpEvent<TaskEntityInfo>>;
|
||||
public tasksTaskgroupIDPut(taskgroupID: number, taskFieldInfo?: TaskFieldInfo, observe: any = 'body', reportProgress: boolean = false, options?: {httpHeaderAccept?: 'application/json', context?: HttpContext}): Observable<any> {
|
||||
if (taskgroupID === null || taskgroupID === undefined) {
|
||||
throw new Error('Required parameter taskgroupID was null or undefined when calling tasksTaskgroupIDPut.');
|
||||
}
|
||||
|
||||
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.put<TaskEntityInfo>(`${this.configuration.basePath}/tasks/${encodeURIComponent(String(taskgroupID))}`,
|
||||
taskFieldInfo,
|
||||
{
|
||||
context: localVarHttpContext,
|
||||
responseType: <any>responseType_,
|
||||
withCredentials: this.configuration.withCredentials,
|
||||
headers: localVarHeaders,
|
||||
observe: observe,
|
||||
reportProgress: reportProgress
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* list tasks
|
||||
* list tasks
|
||||
* @param taskgroupID internal id of taskgroup
|
||||
* @param status scope of listed tasks
|
||||
* @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 tasksTaskgroupIDStatusGet(taskgroupID: number, status: 'all' | 'overdue' | 'upcoming', observe?: 'body', reportProgress?: boolean, options?: {httpHeaderAccept?: 'application/json', context?: HttpContext}): Observable<Array<TaskEntityInfo>>;
|
||||
public tasksTaskgroupIDStatusGet(taskgroupID: number, status: 'all' | 'overdue' | 'upcoming', observe?: 'response', reportProgress?: boolean, options?: {httpHeaderAccept?: 'application/json', context?: HttpContext}): Observable<HttpResponse<Array<TaskEntityInfo>>>;
|
||||
public tasksTaskgroupIDStatusGet(taskgroupID: number, status: 'all' | 'overdue' | 'upcoming', observe?: 'events', reportProgress?: boolean, options?: {httpHeaderAccept?: 'application/json', context?: HttpContext}): Observable<HttpEvent<Array<TaskEntityInfo>>>;
|
||||
public tasksTaskgroupIDStatusGet(taskgroupID: number, status: 'all' | 'overdue' | 'upcoming', observe: any = 'body', reportProgress: boolean = false, options?: {httpHeaderAccept?: 'application/json', context?: HttpContext}): Observable<any> {
|
||||
if (taskgroupID === null || taskgroupID === undefined) {
|
||||
throw new Error('Required parameter taskgroupID was null or undefined when calling tasksTaskgroupIDStatusGet.');
|
||||
}
|
||||
if (status === null || status === undefined) {
|
||||
throw new Error('Required parameter status was null or undefined when calling tasksTaskgroupIDStatusGet.');
|
||||
}
|
||||
|
||||
let localVarHeaders = this.defaultHeaders;
|
||||
|
||||
let localVarCredential: string | undefined;
|
||||
// authentication (API_TOKEN) required
|
||||
localVarCredential = this.configuration.lookupCredential('API_TOKEN');
|
||||
if (localVarCredential) {
|
||||
localVarHeaders = localVarHeaders.set('Authorization', 'Bearer ' + localVarCredential);
|
||||
}
|
||||
|
||||
let localVarHttpHeaderAcceptSelected: string | undefined = options && options.httpHeaderAccept;
|
||||
if (localVarHttpHeaderAcceptSelected === undefined) {
|
||||
// to determine the Accept header
|
||||
const httpHeaderAccepts: string[] = [
|
||||
'application/json'
|
||||
];
|
||||
localVarHttpHeaderAcceptSelected = this.configuration.selectHeaderAccept(httpHeaderAccepts);
|
||||
}
|
||||
if (localVarHttpHeaderAcceptSelected !== undefined) {
|
||||
localVarHeaders = localVarHeaders.set('Accept', localVarHttpHeaderAcceptSelected);
|
||||
}
|
||||
|
||||
let localVarHttpContext: HttpContext | undefined = options && options.context;
|
||||
if (localVarHttpContext === undefined) {
|
||||
localVarHttpContext = new HttpContext();
|
||||
}
|
||||
|
||||
|
||||
let responseType_: 'text' | 'json' = 'json';
|
||||
if(localVarHttpHeaderAcceptSelected && localVarHttpHeaderAcceptSelected.startsWith('text')) {
|
||||
responseType_ = 'text';
|
||||
}
|
||||
|
||||
return this.httpClient.get<Array<TaskEntityInfo>>(`${this.configuration.basePath}/tasks/${encodeURIComponent(String(taskgroupID))}/${encodeURIComponent(String(status))}`,
|
||||
{
|
||||
context: localVarHttpContext,
|
||||
responseType: <any>responseType_,
|
||||
withCredentials: this.configuration.withCredentials,
|
||||
headers: localVarHeaders,
|
||||
observe: observe,
|
||||
reportProgress: reportProgress
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
}
|
@ -20,6 +20,8 @@ import { Observable } from 'rxjs';
|
||||
|
||||
import { InlineResponse200 } from '../model/models';
|
||||
import { InlineResponse403 } from '../model/models';
|
||||
import { SimpleStatusResponse } from '../model/models';
|
||||
import { TaskgroupDetailInfo } from '../model/models';
|
||||
import { TaskgroupEntityInfo } from '../model/models';
|
||||
import { TaskgroupFieldInfo } from '../model/models';
|
||||
|
||||
@ -264,6 +266,65 @@ export class TaskgroupService {
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* clears tasks
|
||||
* Deletes all tasks of that taskgroup
|
||||
* @param taskgroupID internal id of taskgroup
|
||||
* @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 taskgroupsTaskgroupIDClearDelete(taskgroupID: number, observe?: 'body', reportProgress?: boolean, options?: {httpHeaderAccept?: 'application/json', context?: HttpContext}): Observable<SimpleStatusResponse>;
|
||||
public taskgroupsTaskgroupIDClearDelete(taskgroupID: number, observe?: 'response', reportProgress?: boolean, options?: {httpHeaderAccept?: 'application/json', context?: HttpContext}): Observable<HttpResponse<SimpleStatusResponse>>;
|
||||
public taskgroupsTaskgroupIDClearDelete(taskgroupID: number, observe?: 'events', reportProgress?: boolean, options?: {httpHeaderAccept?: 'application/json', context?: HttpContext}): Observable<HttpEvent<SimpleStatusResponse>>;
|
||||
public taskgroupsTaskgroupIDClearDelete(taskgroupID: number, observe: any = 'body', reportProgress: boolean = false, options?: {httpHeaderAccept?: 'application/json', context?: HttpContext}): Observable<any> {
|
||||
if (taskgroupID === null || taskgroupID === undefined) {
|
||||
throw new Error('Required parameter taskgroupID was null or undefined when calling taskgroupsTaskgroupIDClearDelete.');
|
||||
}
|
||||
|
||||
let localVarHeaders = this.defaultHeaders;
|
||||
|
||||
let localVarCredential: string | undefined;
|
||||
// authentication (API_TOKEN) required
|
||||
localVarCredential = this.configuration.lookupCredential('API_TOKEN');
|
||||
if (localVarCredential) {
|
||||
localVarHeaders = localVarHeaders.set('Authorization', 'Bearer ' + localVarCredential);
|
||||
}
|
||||
|
||||
let localVarHttpHeaderAcceptSelected: string | undefined = options && options.httpHeaderAccept;
|
||||
if (localVarHttpHeaderAcceptSelected === undefined) {
|
||||
// to determine the Accept header
|
||||
const httpHeaderAccepts: string[] = [
|
||||
'application/json'
|
||||
];
|
||||
localVarHttpHeaderAcceptSelected = this.configuration.selectHeaderAccept(httpHeaderAccepts);
|
||||
}
|
||||
if (localVarHttpHeaderAcceptSelected !== undefined) {
|
||||
localVarHeaders = localVarHeaders.set('Accept', localVarHttpHeaderAcceptSelected);
|
||||
}
|
||||
|
||||
let localVarHttpContext: HttpContext | undefined = options && options.context;
|
||||
if (localVarHttpContext === undefined) {
|
||||
localVarHttpContext = new HttpContext();
|
||||
}
|
||||
|
||||
|
||||
let responseType_: 'text' | 'json' = 'json';
|
||||
if(localVarHttpHeaderAcceptSelected && localVarHttpHeaderAcceptSelected.startsWith('text')) {
|
||||
responseType_ = 'text';
|
||||
}
|
||||
|
||||
return this.httpClient.delete<SimpleStatusResponse>(`${this.configuration.basePath}/taskgroups/${encodeURIComponent(String(taskgroupID))}/clear`,
|
||||
{
|
||||
context: localVarHttpContext,
|
||||
responseType: <any>responseType_,
|
||||
withCredentials: this.configuration.withCredentials,
|
||||
headers: localVarHeaders,
|
||||
observe: observe,
|
||||
reportProgress: reportProgress
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* deletes taskgroup
|
||||
* deletes taskgroup
|
||||
@ -330,9 +391,9 @@ export class TaskgroupService {
|
||||
* @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 taskgroupsTaskgroupIDGet(taskgroupID: number, observe?: 'body', reportProgress?: boolean, options?: {httpHeaderAccept?: 'application/json', context?: HttpContext}): Observable<Array<TaskgroupEntityInfo>>;
|
||||
public taskgroupsTaskgroupIDGet(taskgroupID: number, observe?: 'response', reportProgress?: boolean, options?: {httpHeaderAccept?: 'application/json', context?: HttpContext}): Observable<HttpResponse<Array<TaskgroupEntityInfo>>>;
|
||||
public taskgroupsTaskgroupIDGet(taskgroupID: number, observe?: 'events', reportProgress?: boolean, options?: {httpHeaderAccept?: 'application/json', context?: HttpContext}): Observable<HttpEvent<Array<TaskgroupEntityInfo>>>;
|
||||
public taskgroupsTaskgroupIDGet(taskgroupID: number, observe?: 'body', reportProgress?: boolean, options?: {httpHeaderAccept?: 'application/json', context?: HttpContext}): Observable<TaskgroupDetailInfo>;
|
||||
public taskgroupsTaskgroupIDGet(taskgroupID: number, observe?: 'response', reportProgress?: boolean, options?: {httpHeaderAccept?: 'application/json', context?: HttpContext}): Observable<HttpResponse<TaskgroupDetailInfo>>;
|
||||
public taskgroupsTaskgroupIDGet(taskgroupID: number, observe?: 'events', reportProgress?: boolean, options?: {httpHeaderAccept?: 'application/json', context?: HttpContext}): Observable<HttpEvent<TaskgroupDetailInfo>>;
|
||||
public taskgroupsTaskgroupIDGet(taskgroupID: number, observe: any = 'body', reportProgress: boolean = false, options?: {httpHeaderAccept?: 'application/json', context?: HttpContext}): Observable<any> {
|
||||
if (taskgroupID === null || taskgroupID === undefined) {
|
||||
throw new Error('Required parameter taskgroupID was null or undefined when calling taskgroupsTaskgroupIDGet.');
|
||||
@ -370,7 +431,7 @@ export class TaskgroupService {
|
||||
responseType_ = 'text';
|
||||
}
|
||||
|
||||
return this.httpClient.get<Array<TaskgroupEntityInfo>>(`${this.configuration.basePath}/taskgroups/${encodeURIComponent(String(taskgroupID))}`,
|
||||
return this.httpClient.get<TaskgroupDetailInfo>(`${this.configuration.basePath}/taskgroups/${encodeURIComponent(String(taskgroupID))}`,
|
||||
{
|
||||
context: localVarHttpContext,
|
||||
responseType: <any>responseType_,
|
||||
|
@ -11,6 +11,10 @@ export * from './propertiesInfo';
|
||||
export * from './propertyInfo';
|
||||
export * from './propertyUpdateRequest';
|
||||
export * from './signUpRequest';
|
||||
export * from './simpleStatusResponse';
|
||||
export * from './taskEntityInfo';
|
||||
export * from './taskFieldInfo';
|
||||
export * from './taskgroupDetailInfo';
|
||||
export * from './taskgroupEntityInfo';
|
||||
export * from './taskgroupFieldInfo';
|
||||
export * from './userAddInfo';
|
||||
|
28
frontend/src/api/model/simpleStatusResponse.ts
Normal file
28
frontend/src/api/model/simpleStatusResponse.ts
Normal file
@ -0,0 +1,28 @@
|
||||
/**
|
||||
* 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 SimpleStatusResponse {
|
||||
/**
|
||||
* Response Status der Request
|
||||
*/
|
||||
status: SimpleStatusResponse.StatusEnum;
|
||||
}
|
||||
export namespace SimpleStatusResponse {
|
||||
export type StatusEnum = 'success' | 'failed';
|
||||
export const StatusEnum = {
|
||||
Success: 'success' as StatusEnum,
|
||||
Failed: 'failed' as StatusEnum
|
||||
};
|
||||
}
|
||||
|
||||
|
44
frontend/src/api/model/taskEntityInfo.ts
Normal file
44
frontend/src/api/model/taskEntityInfo.ts
Normal file
@ -0,0 +1,44 @@
|
||||
/**
|
||||
* 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 TaskEntityInfo {
|
||||
/**
|
||||
* internal id of task
|
||||
*/
|
||||
taskID: number;
|
||||
/**
|
||||
* name of task
|
||||
*/
|
||||
taskName: string;
|
||||
/**
|
||||
* expected time to finish task
|
||||
*/
|
||||
eta: number;
|
||||
/**
|
||||
* date from which the task can be started
|
||||
*/
|
||||
startDate: string;
|
||||
/**
|
||||
* date until the task has to be finished
|
||||
*/
|
||||
deadline: string;
|
||||
/**
|
||||
* determines whether the task is overdue
|
||||
*/
|
||||
overdue: boolean;
|
||||
/**
|
||||
* determines whether the task is finished
|
||||
*/
|
||||
finished: boolean;
|
||||
}
|
||||
|
32
frontend/src/api/model/taskFieldInfo.ts
Normal file
32
frontend/src/api/model/taskFieldInfo.ts
Normal file
@ -0,0 +1,32 @@
|
||||
/**
|
||||
* 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 TaskFieldInfo {
|
||||
/**
|
||||
* name of task
|
||||
*/
|
||||
taskName: string;
|
||||
/**
|
||||
* expected time to finish task
|
||||
*/
|
||||
eta: number;
|
||||
/**
|
||||
* date from which the task can be started
|
||||
*/
|
||||
startDate: string;
|
||||
/**
|
||||
* date until the task has to be finished
|
||||
*/
|
||||
deadline: string;
|
||||
}
|
||||
|
20
frontend/src/api/model/taskgroupDetailInfo.ts
Normal file
20
frontend/src/api/model/taskgroupDetailInfo.ts
Normal file
@ -0,0 +1,20 @@
|
||||
/**
|
||||
* API Title
|
||||
* No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator)
|
||||
*
|
||||
* The version of the OpenAPI document: 1.0
|
||||
*
|
||||
*
|
||||
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
|
||||
* https://openapi-generator.tech
|
||||
* Do not edit the class manually.
|
||||
*/
|
||||
import { TaskgroupEntityInfo } from './taskgroupEntityInfo';
|
||||
|
||||
|
||||
export interface TaskgroupDetailInfo {
|
||||
children: Array<TaskgroupEntityInfo>;
|
||||
ancestors: Array<TaskgroupEntityInfo>;
|
||||
taskgroupInfo: TaskgroupEntityInfo;
|
||||
}
|
||||
|
@ -20,6 +20,5 @@ export interface TaskgroupEntityInfo {
|
||||
* name of taskgroup
|
||||
*/
|
||||
taskgroupName: string;
|
||||
parentTaskgroup: TaskgroupEntityInfo;
|
||||
}
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
import { Component, OnInit } from '@angular/core';
|
||||
import {PropertiesInfo, PropertiesService, PropertyInfo, UserInfo} from "../../../api";
|
||||
import {Router} from "@angular/router";
|
||||
import {MatSnackBar} from "@angular/material/snack-bar";
|
||||
import {MatLegacySnackBar as MatSnackBar} from "@angular/material/legacy-snack-bar";
|
||||
|
||||
@Component({
|
||||
selector: 'app-settings',
|
||||
|
@ -1,8 +1,8 @@
|
||||
import {Component, Inject, OnInit, Output} from '@angular/core';
|
||||
import {MAT_DIALOG_DATA, MatDialogRef} from "@angular/material/dialog";
|
||||
import {MAT_LEGACY_DIALOG_DATA as MAT_DIALOG_DATA, MatLegacyDialogRef as MatDialogRef} from "@angular/material/legacy-dialog";
|
||||
import {UserInfo, UsersService} from "../../../../api";
|
||||
import {LoginInfoTypes} from "../../../auth/login/login.component";
|
||||
import {MatSnackBar} from "@angular/material/snack-bar";
|
||||
import {MatLegacySnackBar as MatSnackBar} from "@angular/material/legacy-snack-bar";
|
||||
|
||||
@Component({
|
||||
selector: 'app-delete-confirmation',
|
||||
|
@ -1,8 +1,8 @@
|
||||
import {Component, Inject, OnInit} from '@angular/core';
|
||||
import {MAT_DIALOG_DATA, MatDialogRef} from "@angular/material/dialog";
|
||||
import {MAT_DIALOG_DATA as MAT_DIALOG_DATA, MatDialogRef as MatDialogRef} from "@angular/material/dialog";
|
||||
import {UserInfo, UsersService} from "../../../../api";
|
||||
import {MatSnackBar} from "@angular/material/snack-bar";
|
||||
import {AbstractControl, FormControl, ValidationErrors, Validators} from "@angular/forms";
|
||||
import {MatSnackBar as MatSnackBar} from "@angular/material/snack-bar";
|
||||
import {AbstractControl, UntypedFormControl, ValidationErrors, Validators} from "@angular/forms";
|
||||
import {EditData} from "./edit-data";
|
||||
|
||||
|
||||
@ -24,22 +24,22 @@ export class EditComponent implements OnInit {
|
||||
|
||||
adminUpdateDisabled: boolean = false;
|
||||
|
||||
usernameFormControl = new FormControl('', [Validators.required, Validators.minLength(3), Validators.maxLength(32)])
|
||||
emailFormControl = new FormControl('', [Validators.required, Validators.email])
|
||||
usernameFormControl = new UntypedFormControl('', [Validators.required, Validators.minLength(3), Validators.maxLength(32)])
|
||||
emailFormControl = new UntypedFormControl('', [Validators.required, Validators.email])
|
||||
|
||||
passwordEditControl = new FormControl('', [
|
||||
passwordEditControl = new UntypedFormControl('', [
|
||||
(control: AbstractControl): ValidationErrors | null => {
|
||||
return control.value.length > 0 && control.value.length < 6 ? {minlength: {value: control.value}} : null
|
||||
},
|
||||
])
|
||||
passwordAddControl = new FormControl('', [Validators.required, Validators.minLength(6)])
|
||||
passwordAddControl = new UntypedFormControl('', [Validators.required, Validators.minLength(6)])
|
||||
|
||||
passwordDuplicateEditControl = new FormControl('', [
|
||||
passwordDuplicateEditControl = new UntypedFormControl('', [
|
||||
(control: AbstractControl): ValidationErrors | null => {
|
||||
return control.value != this.password ? {duplicate: {value: control.value}} : null
|
||||
}
|
||||
])
|
||||
passwordDuplicateAddControl = new FormControl('', [
|
||||
passwordDuplicateAddControl = new UntypedFormControl('', [
|
||||
Validators.required,
|
||||
Validators.minLength(6),
|
||||
(control: AbstractControl): ValidationErrors | null => {
|
||||
|
@ -1,11 +1,11 @@
|
||||
import {ChangeDetectorRef, Component, OnInit} from '@angular/core';
|
||||
import {UserInfo, UsersService} from "../../../api";
|
||||
import {MatDialog} from "@angular/material/dialog";
|
||||
import {MatDialog as MatDialog} from "@angular/material/dialog";
|
||||
import {LoginComponent} from "../../auth/login/login.component";
|
||||
import {DeleteConfirmationComponent} from "./delete-confirmation/delete-confirmation.component";
|
||||
import {CollectionViewer, DataSource} from "@angular/cdk/collections";
|
||||
import {Observable} from "rxjs";
|
||||
import {MatTableDataSource} from "@angular/material/table";
|
||||
import {MatTableDataSource as MatTableDataSource} from "@angular/material/table";
|
||||
import {EditComponent} from "./edit/edit.component";
|
||||
import {EditData} from "./edit/edit-data";
|
||||
|
||||
|
@ -9,25 +9,22 @@ import {HttpClient, HttpClientModule, HttpHandler} from "@angular/common/http";
|
||||
import {ApiModule, Configuration} from "../api";
|
||||
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
|
||||
import {MatToolbarModule} from "@angular/material/toolbar";
|
||||
import {MatButtonModule} from "@angular/material/button";
|
||||
import {MatIconModule} from "@angular/material/icon";
|
||||
import {MatDialogModule} from "@angular/material/dialog";
|
||||
import {MatFormFieldModule} from "@angular/material/form-field";
|
||||
import {MatInputModule} from "@angular/material/input";
|
||||
import {MatProgressSpinnerModule} from "@angular/material/progress-spinner";
|
||||
import {MatSnackBar, MatSnackBarModule} from "@angular/material/snack-bar";
|
||||
import {MatMenuModule} from "@angular/material/menu";
|
||||
import {MatDialogModule as MatDialogModule} from "@angular/material/dialog";
|
||||
import {MatFormFieldModule as MatFormFieldModule} from "@angular/material/form-field";
|
||||
import {MatInputModule as MatInputModule} from "@angular/material/input";
|
||||
import {MatProgressSpinnerModule as MatProgressSpinnerModule} from "@angular/material/progress-spinner";
|
||||
import {MatSnackBar as MatSnackBar, MatSnackBarModule as MatSnackBarModule} from "@angular/material/snack-bar";
|
||||
import { AdminDashboardComponent } from './admin-dashboard/admin-dashboard.component';
|
||||
import { MainComponent } from './main/main.component';
|
||||
import { UsermanagementComponent } from './admin-dashboard/usermanagement/usermanagement.component';
|
||||
import {MatTabsModule} from "@angular/material/tabs";
|
||||
|
||||
import {AuthService} from "./auth.service";
|
||||
import {environment} from "../environments/environment";
|
||||
import {MatTableModule} from "@angular/material/table";
|
||||
import {MatCheckboxModule} from "@angular/material/checkbox";
|
||||
|
||||
import { DeleteConfirmationComponent } from './admin-dashboard/usermanagement/delete-confirmation/delete-confirmation.component';
|
||||
import { EditComponent } from './admin-dashboard/usermanagement/edit/edit.component';
|
||||
import {MatCardModule} from "@angular/material/card";
|
||||
|
||||
import {UserSettingsComponent} from "./user-settings/user-settings.component";
|
||||
import {AccountSettingsComponent} from "./user-settings/account-settings/account-settings.component";
|
||||
import { ChangePasswordComponent } from './user-settings/account-settings/change-password/change-password.component';
|
||||
@ -35,10 +32,27 @@ import { ManageEmailComponent } from './user-settings/account-settings/manage-em
|
||||
import { DeleteAccountComponent } from './user-settings/account-settings/delete-account/delete-account.component';
|
||||
import { RegistrationComponent } from './auth/registration/registration.component';
|
||||
import { SettingsComponent } from './admin-dashboard/settings/settings.component';
|
||||
import {MatListModule} from "@angular/material/list";
|
||||
|
||||
import { TaskgroupDashboardComponent } from './taskgroups/taskgroup-dashboard/taskgroup-dashboard.component';
|
||||
import { TaskgroupCreationComponent } from './taskgroups/taskgroup-creation/taskgroup-creation.component';
|
||||
import { TaskgroupDeletionComponent } from './taskgroups/taskgroup-deletion/taskgroup-deletion.component';
|
||||
import { TaskEditorComponent } from './tasks/task-editor/task-editor.component';
|
||||
import {MatDatepickerModule} from "@angular/material/datepicker";
|
||||
import {MatButtonModule} from "@angular/material/button";
|
||||
import {MatMenuModule} from "@angular/material/menu";
|
||||
import {MatTabsModule} from "@angular/material/tabs";
|
||||
import {MatTableModule} from "@angular/material/table";
|
||||
import {MatCheckboxModule} from "@angular/material/checkbox";
|
||||
import {MatCardModule} from "@angular/material/card";
|
||||
import {MatListModule} from "@angular/material/list";
|
||||
import {DateAdapter, MAT_DATE_FORMATS, MAT_DATE_LOCALE, MatNativeDateModule} from "@angular/material/core";
|
||||
import {MatMomentDateModule, MomentDateModule} from "@angular/material-moment-adapter";
|
||||
import { TaskDashboardComponent } from './tasks/task-dashboard/task-dashboard.component';
|
||||
import {MatSlideToggleModule} from "@angular/material/slide-toggle";
|
||||
import {MatSortModule} from "@angular/material/sort";
|
||||
import {MatPaginatorModule} from "@angular/material/paginator";
|
||||
import { ClearTaskDialogComponent } from './tasks/clear-task-dialog/clear-task-dialog.component';
|
||||
import { NavigationLinkListComponent } from './navigation-link-list/navigation-link-list.component';
|
||||
|
||||
@NgModule({
|
||||
declarations: [
|
||||
@ -58,7 +72,11 @@ import { TaskgroupDeletionComponent } from './taskgroups/taskgroup-deletion/task
|
||||
SettingsComponent,
|
||||
TaskgroupDashboardComponent,
|
||||
TaskgroupCreationComponent,
|
||||
TaskgroupDeletionComponent
|
||||
TaskgroupDeletionComponent,
|
||||
TaskEditorComponent,
|
||||
TaskDashboardComponent,
|
||||
ClearTaskDialogComponent,
|
||||
NavigationLinkListComponent
|
||||
],
|
||||
imports: [
|
||||
BrowserModule,
|
||||
@ -81,7 +99,15 @@ import { TaskgroupDeletionComponent } from './taskgroups/taskgroup-deletion/task
|
||||
MatCheckboxModule,
|
||||
MatCardModule,
|
||||
ReactiveFormsModule,
|
||||
MatListModule
|
||||
MatListModule,
|
||||
MatDatepickerModule,
|
||||
MatInputModule,
|
||||
MatDatepickerModule,
|
||||
MatMomentDateModule,
|
||||
FormsModule,
|
||||
MatSlideToggleModule,
|
||||
MatSortModule,
|
||||
MatPaginatorModule
|
||||
],
|
||||
providers: [
|
||||
HttpClientModule,
|
||||
@ -108,8 +134,7 @@ import { TaskgroupDeletionComponent } from './taskgroups/taskgroup-deletion/task
|
||||
),
|
||||
deps: [AuthService],
|
||||
multi: false
|
||||
}
|
||||
|
||||
},
|
||||
],
|
||||
bootstrap: [AppComponent]
|
||||
})
|
||||
|
@ -1,8 +1,8 @@
|
||||
import {Component, Inject, OnInit} from '@angular/core';
|
||||
import {LoginService, PropertiesService} from "../../../api";
|
||||
import {MAT_DIALOG_DATA, MatDialog, MatDialogRef} from "@angular/material/dialog";
|
||||
import {MAT_DIALOG_DATA as MAT_DIALOG_DATA, MatDialog as MatDialog, MatDialogRef as MatDialogRef} from "@angular/material/dialog";
|
||||
import {Router} from "@angular/router";
|
||||
import {MatSnackBar} from "@angular/material/snack-bar";
|
||||
import {MatSnackBar as MatSnackBar} from "@angular/material/snack-bar";
|
||||
import {AuthService} from "../../auth.service";
|
||||
import {RegistrationComponent} from "../registration/registration.component";
|
||||
|
||||
|
@ -1,12 +1,12 @@
|
||||
import { Component, OnInit } from '@angular/core';
|
||||
import {MatDialog, MatDialogRef} from "@angular/material/dialog";
|
||||
import {MatDialog as MatDialog, MatDialogRef as MatDialogRef} from "@angular/material/dialog";
|
||||
import {LoginService} from "../../../api";
|
||||
import {Router} from "@angular/router";
|
||||
import {MatSnackBar} from "@angular/material/snack-bar";
|
||||
import {MatSnackBar as MatSnackBar} from "@angular/material/snack-bar";
|
||||
import {AuthService} from "../../auth.service";
|
||||
import {LoginComponent} from "../login/login.component";
|
||||
import {LoginDialogServiceService} from "../../login-dialog-service.service";
|
||||
import {AbstractControl, FormControl, ValidationErrors, Validators} from "@angular/forms";
|
||||
import {AbstractControl, UntypedFormControl, ValidationErrors, Validators} from "@angular/forms";
|
||||
|
||||
@Component({
|
||||
selector: 'app-registration',
|
||||
@ -23,10 +23,10 @@ export class RegistrationComponent implements OnInit {
|
||||
pending: boolean = false;
|
||||
isAuth: boolean = false;
|
||||
|
||||
usernameControl = new FormControl('', [Validators.required, Validators.minLength(3)]);
|
||||
emailControl = new FormControl('', [Validators.required, Validators.email])
|
||||
passwordControl = new FormControl('', [Validators.required, Validators.minLength(6)]);
|
||||
passwordDuplicateControl = new FormControl('', [
|
||||
usernameControl = new UntypedFormControl('', [Validators.required, Validators.minLength(3)]);
|
||||
emailControl = new UntypedFormControl('', [Validators.required, Validators.email])
|
||||
passwordControl = new UntypedFormControl('', [Validators.required, Validators.minLength(6)]);
|
||||
passwordDuplicateControl = new UntypedFormControl('', [
|
||||
Validators.required,
|
||||
Validators.minLength(6),
|
||||
(control: AbstractControl): ValidationErrors | null => {
|
||||
|
@ -1,5 +1,5 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import {MatDialog} from "@angular/material/dialog";
|
||||
import {MatDialog as MatDialog} from "@angular/material/dialog";
|
||||
import {LoginComponent, LoginInfoTypes} from "./auth/login/login.component";
|
||||
import {Observable} from "rxjs";
|
||||
|
||||
|
@ -0,0 +1,23 @@
|
||||
|
||||
.navLink {
|
||||
text-decoration: underline;
|
||||
color: black;
|
||||
margin-right: 5px;
|
||||
margin-left: 3px;
|
||||
}
|
||||
|
||||
.navLink-disabled {
|
||||
text-decoration: none;
|
||||
color: grey;
|
||||
|
||||
}
|
||||
|
||||
.navLink-bar {
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.link-separation {
|
||||
text-decoration: none;
|
||||
padding-right: 5px;
|
||||
}
|
||||
|
@ -0,0 +1,8 @@
|
||||
<mat-card class="navLink-bar">
|
||||
<mat-card-content>
|
||||
<span *ngFor="let navigationLink of navigationLinks; index as i">
|
||||
<span class="link-seperation" *ngIf="i !== 0">/</span>
|
||||
<a class="navLink" [routerLink]="navigationLink.routerLink" [class.navLink-disabled]="i == navigationLinks.length-1">{{navigationLink.linkText}}</a>
|
||||
</span>
|
||||
</mat-card-content>
|
||||
</mat-card>
|
@ -0,0 +1,21 @@
|
||||
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
|
||||
import { NavigationLinkListComponent } from './navigation-link-list.component';
|
||||
|
||||
describe('NavigationLinkListComponent', () => {
|
||||
let component: NavigationLinkListComponent;
|
||||
let fixture: ComponentFixture<NavigationLinkListComponent>;
|
||||
|
||||
beforeEach(() => {
|
||||
TestBed.configureTestingModule({
|
||||
declarations: [NavigationLinkListComponent]
|
||||
});
|
||||
fixture = TestBed.createComponent(NavigationLinkListComponent);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
@ -0,0 +1,40 @@
|
||||
import {Component, Input, OnInit} from '@angular/core';
|
||||
|
||||
export interface NavigationLink {
|
||||
routerLink: string[],
|
||||
linkText: string
|
||||
}
|
||||
|
||||
@Component({
|
||||
selector: 'app-navigation-link-list',
|
||||
templateUrl: './navigation-link-list.component.html',
|
||||
styleUrls: ['./navigation-link-list.component.css']
|
||||
})
|
||||
export class NavigationLinkListComponent implements OnInit{
|
||||
|
||||
|
||||
|
||||
@Input() navigationLinks: NavigationLink[] = []
|
||||
|
||||
ngOnInit(): void {
|
||||
|
||||
}
|
||||
|
||||
addNavigationLink(linkText: string, link: string[]) {
|
||||
const navigationLink: NavigationLink = {
|
||||
linkText: linkText,
|
||||
routerLink: link
|
||||
}
|
||||
|
||||
if(this.navigationLinks.find(searchedLink => searchedLink.linkText === linkText) === undefined) {
|
||||
this.navigationLinks.push(navigationLink);
|
||||
}
|
||||
}
|
||||
|
||||
removeLink(linkText: string) {
|
||||
this.navigationLinks = this.navigationLinks.filter(link => link.linkText === linkText);
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
@ -1,12 +1,11 @@
|
||||
import {Component, Inject, OnInit} from '@angular/core';
|
||||
import {FormControl, Validators} from "@angular/forms";
|
||||
import {MAT_DIALOG_DATA, MatDialogRef} from "@angular/material/dialog";
|
||||
import {TaskgroupEntityInfo, TaskgroupService} from "../../../api";
|
||||
import {error} from "@angular/compiler/src/util";
|
||||
import {MatSnackBar} from "@angular/material/snack-bar";
|
||||
import {ActivatedRoute} from "@angular/router";
|
||||
import {UntypedFormControl, Validators} from "@angular/forms";
|
||||
import {MAT_DIALOG_DATA as MAT_DIALOG_DATA, MatDialogRef as MatDialogRef} from "@angular/material/dialog";
|
||||
import {TaskgroupService} from "../../../api";
|
||||
import {MatSnackBar as MatSnackBar} from "@angular/material/snack-bar";
|
||||
import {TaskgroupCreationData} from "./TaskgroupCreationData";
|
||||
|
||||
|
||||
@Component({
|
||||
selector: 'app-taskgroup-creation',
|
||||
templateUrl: './taskgroup-creation.component.html',
|
||||
@ -14,7 +13,7 @@ import {TaskgroupCreationData} from "./TaskgroupCreationData";
|
||||
})
|
||||
export class TaskgroupCreationComponent implements OnInit {
|
||||
|
||||
nameCtrl = new FormControl('', [Validators.required, Validators.maxLength(255)])
|
||||
nameCtrl = new UntypedFormControl('', [Validators.required, Validators.maxLength(255)])
|
||||
pending: boolean = false
|
||||
|
||||
constructor(private dialogRef: MatDialogRef<TaskgroupCreationComponent>,
|
||||
|
@ -1,6 +1,6 @@
|
||||
.container {
|
||||
margin: 20px auto;
|
||||
width: 60%;
|
||||
width: 70%;
|
||||
}
|
||||
|
||||
.spacer {
|
||||
@ -15,27 +15,23 @@
|
||||
}
|
||||
}
|
||||
|
||||
.navLink {
|
||||
text-decoration: underline;
|
||||
color: black;
|
||||
margin-right: 5px;
|
||||
}
|
||||
|
||||
.navLink-disabled {
|
||||
text-decoration: none;
|
||||
color: grey;
|
||||
|
||||
}
|
||||
|
||||
.navLink-bar {
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
#addTaskgroupBtn {
|
||||
margin-top: 20px;
|
||||
float: right;
|
||||
}
|
||||
|
||||
#addTaskBtn {
|
||||
margin-top: 20px;
|
||||
float: left;
|
||||
}
|
||||
|
||||
.edit-btn {
|
||||
background-color: #6e6e6e;
|
||||
color: white;
|
||||
}
|
||||
|
||||
#task-dashboard-container {
|
||||
width: 100%;
|
||||
margin-top: 20px;
|
||||
}
|
||||
|
||||
|
@ -1,10 +1,5 @@
|
||||
<div class="container">
|
||||
<mat-card class="navLink-bar">
|
||||
<mat-card-content>
|
||||
<a class="navLink" routerLink="/">Dashboard</a>
|
||||
<a class="navLink-disabled">/ Taskgroups</a>
|
||||
</mat-card-content>
|
||||
</mat-card>
|
||||
<app-navigation-link-list #navLinkList [navigationLinks]="defaultNavigationLinkPath"></app-navigation-link-list>
|
||||
|
||||
<mat-card *ngFor="let taskgroup of taskgroups">
|
||||
<mat-card-content>
|
||||
@ -15,5 +10,16 @@
|
||||
</mat-card-content>
|
||||
|
||||
</mat-card>
|
||||
|
||||
<mat-card style="width: 100%" *ngIf="taskgroupID >= 0">
|
||||
<mat-card-content>
|
||||
<app-task-dashboard #taskDashboard [taskgroupID]="taskgroupID"></app-task-dashboard>
|
||||
</mat-card-content>
|
||||
</mat-card>
|
||||
<div style="width: 100%">
|
||||
<button id="addTaskBtn" *ngIf="taskgroupID >= 0" mat-raised-button color="primary" (click)="openTaskCreation()">Create New Task</button>
|
||||
<button id="addTaskgroupBtn" mat-raised-button color="primary" (click)="openTaskgroupCreation()">Create new Taskgroup</button>
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
|
@ -1,9 +1,13 @@
|
||||
import { Component, OnInit } from '@angular/core';
|
||||
import {MatDialog} from "@angular/material/dialog";
|
||||
import {Component, OnInit, ViewChild} from '@angular/core';
|
||||
import {MatDialog as MatDialog} from "@angular/material/dialog";
|
||||
import {TaskgroupCreationComponent} from "../taskgroup-creation/taskgroup-creation.component";
|
||||
import {TaskgroupEntityInfo, TaskgroupService} from "../../../api";
|
||||
import {TaskgroupDeletionComponent} from "../taskgroup-deletion/taskgroup-deletion.component";
|
||||
import {ActivatedRoute} from "@angular/router";
|
||||
import {TaskEditorComponent} from "../../tasks/task-editor/task-editor.component";
|
||||
import {TaskEditorData} from "../../tasks/task-editor/TaskEditorData";
|
||||
import {TaskDashboardComponent} from "../../tasks/task-dashboard/task-dashboard.component";
|
||||
import {NavigationLink, NavigationLinkListComponent} from "../../navigation-link-list/navigation-link-list.component";
|
||||
|
||||
@Component({
|
||||
selector: 'app-taskgroup-dashboard',
|
||||
@ -17,7 +21,21 @@ export class TaskgroupDashboardComponent implements OnInit {
|
||||
private activatedRoute: ActivatedRoute) { }
|
||||
|
||||
taskgroups: TaskgroupEntityInfo[] = []
|
||||
taskgroup: TaskgroupEntityInfo | undefined
|
||||
taskgroupPath: TaskgroupEntityInfo[] = []
|
||||
taskgroupID: number = -1;
|
||||
@ViewChild("taskDashboard") taskDashboard: TaskDashboardComponent | undefined
|
||||
@ViewChild('navLinkList') navLinkListComponent: NavigationLinkListComponent | undefined
|
||||
defaultNavigationLinkPath: NavigationLink[] = [
|
||||
{
|
||||
linkText: "Dashboard",
|
||||
routerLink: ['/']
|
||||
},
|
||||
{
|
||||
linkText: "Taskgroups",
|
||||
routerLink: ["/taskgroups"]
|
||||
}
|
||||
]
|
||||
|
||||
ngOnInit(): void {
|
||||
this.activatedRoute.paramMap.subscribe(params => {
|
||||
@ -25,7 +43,13 @@ export class TaskgroupDashboardComponent implements OnInit {
|
||||
this.taskgroupID = Number(params.get('taskgroupID'));
|
||||
this.taskgroupService.taskgroupsTaskgroupIDGet(this.taskgroupID).subscribe({
|
||||
next: resp => {
|
||||
this.taskgroups = resp
|
||||
this.taskgroups = resp.children
|
||||
this.taskgroupPath = resp.ancestors
|
||||
this.taskgroup = resp.taskgroupInfo;
|
||||
this.navLinkListComponent!.addNavigationLink(this.taskgroup.taskgroupName, ['/taskgroups', this.taskgroup.taskgroupID.toString()])
|
||||
this.taskgroupPath.forEach(taskgroupEntity => {
|
||||
this.navLinkListComponent!.addNavigationLink(taskgroupEntity.taskgroupName, ['/taskgroups', taskgroupEntity.taskgroupID.toString()]);
|
||||
})
|
||||
}
|
||||
})
|
||||
} else {
|
||||
@ -65,4 +89,17 @@ export class TaskgroupDashboardComponent implements OnInit {
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
openTaskCreation() {
|
||||
const editorData: TaskEditorData = {
|
||||
task: undefined,
|
||||
taskgroupID: this.taskgroupID
|
||||
}
|
||||
const dialogRef = this.dialog.open(TaskEditorComponent, {data: editorData, width: "600px"})
|
||||
dialogRef.afterClosed().subscribe(res => {
|
||||
if(res != undefined) {
|
||||
this.taskDashboard!.addTask(res);
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
import {Component, Inject, OnInit} from '@angular/core';
|
||||
import {MAT_DIALOG_DATA, MatDialogRef} from "@angular/material/dialog";
|
||||
import {MAT_DIALOG_DATA as MAT_DIALOG_DATA, MatDialogRef as MatDialogRef} from "@angular/material/dialog";
|
||||
import {TaskgroupEntityInfo, TaskgroupService} from "../../../api";
|
||||
import {MatSnackBar} from "@angular/material/snack-bar";
|
||||
import {MatSnackBar as MatSnackBar} from "@angular/material/snack-bar";
|
||||
|
||||
@Component({
|
||||
selector: 'app-taskgroup-deletion',
|
||||
|
@ -0,0 +1,3 @@
|
||||
.deleteSetttings {
|
||||
margin-right: 20px;
|
||||
}
|
@ -0,0 +1,13 @@
|
||||
<h1 mat-dialog-title>Clear Tasks ({{editorData.taskgroupID}})</h1>
|
||||
<div mat-dialog-content>
|
||||
<p>Are you sure you want to clear the Tasks? This <b>cannot</b> be <b>undone!</b></p>
|
||||
<mat-slide-toggle class="deleteSetttings">Finished Tasks <b>( {{finishedTasks}}Tasks)</b></mat-slide-toggle>
|
||||
<mat-slide-toggle class="deleteSetttings">Overdue Tasks <b>({{overdueTasks}} Tasks)</b></mat-slide-toggle>
|
||||
<mat-slide-toggle class="deleteSetttings">Unfinished Tasks <b>( {{unfinishedTasks}}Tasks)</b></mat-slide-toggle>
|
||||
<mat-slide-toggle class="deleteSetttings">Upcoming Tasks <b>({{upcomingTasks}} Tasks)</b></mat-slide-toggle>
|
||||
</div>
|
||||
|
||||
<div mat-dialog-actions align="end">
|
||||
<button mat-raised-button (click)="cancel()">Cancel</button>
|
||||
<button mat-raised-button color="warn" (click)="clearTasks()"><mat-icon>delete</mat-icon>Clear</button>
|
||||
</div>
|
@ -0,0 +1,21 @@
|
||||
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
|
||||
import { ClearTaskDialogComponent } from './clear-task-dialog.component';
|
||||
|
||||
describe('ClearTaskDialogComponent', () => {
|
||||
let component: ClearTaskDialogComponent;
|
||||
let fixture: ComponentFixture<ClearTaskDialogComponent>;
|
||||
|
||||
beforeEach(() => {
|
||||
TestBed.configureTestingModule({
|
||||
declarations: [ClearTaskDialogComponent]
|
||||
});
|
||||
fixture = TestBed.createComponent(ClearTaskDialogComponent);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
@ -0,0 +1,69 @@
|
||||
import {Component, Inject, OnInit} from '@angular/core';
|
||||
import {TaskEditorData} from "../task-editor/TaskEditorData";
|
||||
import {TaskEntityInfo, TaskgroupService} from "../../../api";
|
||||
import {MAT_DIALOG_DATA, MatDialogRef} from "@angular/material/dialog";
|
||||
import {MatSnackBar} from "@angular/material/snack-bar";
|
||||
|
||||
export interface ClearTaskDialogData {
|
||||
taskgroupID: number,
|
||||
tasks: TaskEntityInfo[]
|
||||
}
|
||||
@Component({
|
||||
selector: 'app-clear-task-dialog',
|
||||
templateUrl: './clear-task-dialog.component.html',
|
||||
styleUrls: ['./clear-task-dialog.component.css']
|
||||
})
|
||||
export class ClearTaskDialogComponent implements OnInit{
|
||||
|
||||
finishedTasks: number = 0;
|
||||
unfinishedTasks: number = 0;
|
||||
overdueTasks: number = 0;
|
||||
upcomingTasks: number = 0;
|
||||
|
||||
constructor(@Inject(MAT_DIALOG_DATA) public editorData: ClearTaskDialogData,
|
||||
private taskgroupService: TaskgroupService,
|
||||
private dialogRef: MatDialogRef<ClearTaskDialogComponent>,
|
||||
private snackbar: MatSnackBar) {
|
||||
}
|
||||
|
||||
ngOnInit(): void {
|
||||
this.editorData.tasks.forEach(task => {
|
||||
if(task.overdue) {
|
||||
this.overdueTasks +=1;
|
||||
} else {
|
||||
this.upcomingTasks += 1;
|
||||
}
|
||||
|
||||
if(task.finished) {
|
||||
this.finishedTasks += 1;
|
||||
} else {
|
||||
this.unfinishedTasks += 1;
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
cancel() {
|
||||
|
||||
}
|
||||
|
||||
clearTasks() {
|
||||
this.taskgroupService.taskgroupsTaskgroupIDClearDelete(this.editorData.taskgroupID).subscribe({
|
||||
next: resp => {
|
||||
if(resp.status == "success") {
|
||||
const deletedTasks = this.editorData.tasks;
|
||||
this.dialogRef.close(deletedTasks);
|
||||
}
|
||||
},
|
||||
error: err => {
|
||||
if(err.status == 403) {
|
||||
this.snackbar.open("No permission", "", {duration: 2000});
|
||||
} else if(err.status == 404) {
|
||||
this.snackbar.open("Not found", "", {duration: 2000});
|
||||
} else {
|
||||
this.snackbar.open("Unexpected error", "", {duration: 2000});
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
@ -0,0 +1,37 @@
|
||||
|
||||
|
||||
mat-form-field {
|
||||
width: 80%;
|
||||
}
|
||||
|
||||
table {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
|
||||
td, th {
|
||||
width: 25%;
|
||||
}
|
||||
|
||||
.status-indicator {
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
border-radius: 50%;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
.mat-column-status, .mat-column-eta {
|
||||
width: 32px;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.mat-column-edit, .mat-column-delete, .mat-column-finished {
|
||||
width: 32px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
|
||||
#clear-tasks-btn {
|
||||
float: right;
|
||||
margin-top: 10px;
|
||||
}
|
@ -0,0 +1,61 @@
|
||||
<mat-form-field appearance="fill">
|
||||
<mat-label>Search</mat-label>
|
||||
<input matInput (keyup)="applyFilter($event)" placeholder="Search for Taskname" #input>
|
||||
</mat-form-field>
|
||||
|
||||
<!--<mat-slide-toggle style="margin-left: 20px">Show finished tasks</mat-slide-toggle>-->
|
||||
<button id="clear-tasks-btn" (click)="clearTasks()" mat-raised-button color="warn"><mat-icon>delete</mat-icon>Clear Tasks</button>
|
||||
|
||||
<div class="mat-elevation-z8">
|
||||
<table mat-table [dataSource]="datasource" matSort>
|
||||
<ng-container matColumnDef="name">
|
||||
<th mat-header-cell *matHeaderCellDef mat-sort-header> Name </th>
|
||||
<td mat-cell *matCellDef="let task"> {{task.taskName}} </td>
|
||||
</ng-container>
|
||||
<ng-container matColumnDef="eta">
|
||||
<th mat-header-cell *matHeaderCellDef mat-sort-header> ETA </th>
|
||||
<td mat-cell *matCellDef="let task"> {{task.eta}} </td>
|
||||
</ng-container>
|
||||
<ng-container matColumnDef="start">
|
||||
<th mat-header-cell *matHeaderCellDef mat-sort-header> Start </th>
|
||||
<td mat-cell *matCellDef="let task"> {{task.startDate}} </td>
|
||||
</ng-container>
|
||||
<ng-container matColumnDef="deadline">
|
||||
<th mat-header-cell *matHeaderCellDef mat-sort-header> Deadline </th>
|
||||
<td mat-cell *matCellDef="let task"> {{task.deadline}} </td>
|
||||
</ng-container>
|
||||
<ng-container matColumnDef="finished">
|
||||
<th mat-header-cell *matHeaderCellDef mat-sort-header> Finished </th>
|
||||
<td mat-cell *matCellDef="let task">
|
||||
<mat-checkbox [value]="task.finished" [contentEditable]="false" disableRipple="true" (click)="$event.preventDefault()"></mat-checkbox>
|
||||
</td>
|
||||
</ng-container>
|
||||
<ng-container matColumnDef="status">
|
||||
<th mat-header-cell *matHeaderCellDef mat-sort-header> Status </th>
|
||||
<td mat-cell *matCellDef="let task">
|
||||
<div class="status-indicator" [style.background-color]="getStatusOfTask(task)"></div>
|
||||
</td>
|
||||
</ng-container>
|
||||
<ng-container matColumnDef="edit">
|
||||
<th mat-header-cell *matHeaderCellDef mat-sort-header></th>
|
||||
<td mat-cell *matCellDef="let task">
|
||||
<button mat-icon-button color="primary" (click)="editTask(task)"><mat-icon>edit</mat-icon></button>
|
||||
</td>
|
||||
</ng-container>
|
||||
<ng-container matColumnDef="delete">
|
||||
<th mat-header-cell *matHeaderCellDef mat-sort-header></th>
|
||||
<td mat-cell *matCellDef="let task">
|
||||
<button mat-icon-button color="warn" (click)="deleteTask(task)"><mat-icon>delete</mat-icon></button>
|
||||
</td>
|
||||
</ng-container>
|
||||
|
||||
|
||||
<tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
|
||||
<tr mat-row *matRowDef="let row; columns: displayedColumns;"></tr>
|
||||
<!-- Row shown when there is no matching data. -->
|
||||
<tr class="mat-row" *matNoDataRow>
|
||||
<td class="mat-cell" colspan="4">No data matching the filter "{{input.value}}"</td>
|
||||
</tr>
|
||||
</table>
|
||||
<mat-paginator [pageSizeOptions]="[5, 10, 25, 100]" aria-label="Select page of users"></mat-paginator>
|
||||
</div>
|
@ -0,0 +1,21 @@
|
||||
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
|
||||
import { TaskDashboardComponent } from './task-dashboard.component';
|
||||
|
||||
describe('TaskDashboardComponent', () => {
|
||||
let component: TaskDashboardComponent;
|
||||
let fixture: ComponentFixture<TaskDashboardComponent>;
|
||||
|
||||
beforeEach(() => {
|
||||
TestBed.configureTestingModule({
|
||||
declarations: [TaskDashboardComponent]
|
||||
});
|
||||
fixture = TestBed.createComponent(TaskDashboardComponent);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
@ -0,0 +1,102 @@
|
||||
import {Component, Input, OnChanges, ViewChild} from '@angular/core';
|
||||
import {TaskEntityInfo, TaskService} from "../../../api";
|
||||
import {MatPaginator} from "@angular/material/paginator";
|
||||
import {MatSort} from "@angular/material/sort";
|
||||
import {MatTableDataSource} from "@angular/material/table";
|
||||
import {TaskEditorComponent} from "../task-editor/task-editor.component";
|
||||
import {TaskEditorData} from "../task-editor/TaskEditorData";
|
||||
import {MatDialog} from "@angular/material/dialog";
|
||||
import {MatSnackBar} from "@angular/material/snack-bar";
|
||||
import {ClearTaskDialogComponent, ClearTaskDialogData} from "../clear-task-dialog/clear-task-dialog.component";
|
||||
|
||||
@Component({
|
||||
selector: 'app-task-dashboard',
|
||||
templateUrl: './task-dashboard.component.html',
|
||||
styleUrls: ['./task-dashboard.component.css']
|
||||
})
|
||||
export class TaskDashboardComponent implements OnChanges{
|
||||
ngOnChanges(): void {
|
||||
if(this.taskgroupID != undefined) {
|
||||
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!;
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@Input("taskgroupID") taskgroupID: number | undefined
|
||||
@ViewChild(MatPaginator) paginator: MatPaginator | undefined
|
||||
@ViewChild(MatSort) sort: MatSort | undefined
|
||||
|
||||
displayedColumns: string[] = ['status', 'name', 'eta', 'start', 'deadline', 'finished', 'edit', 'delete'];
|
||||
datasource: MatTableDataSource<TaskEntityInfo> = new MatTableDataSource<TaskEntityInfo>();
|
||||
|
||||
constructor(private taskService: TaskService,
|
||||
private dialog: MatDialog,
|
||||
private snackbar: MatSnackBar) {
|
||||
}
|
||||
|
||||
|
||||
applyFilter(event: Event) {
|
||||
const filterValue = (event.target as HTMLInputElement).value;
|
||||
this.datasource.filter = filterValue.trim().toLowerCase();
|
||||
|
||||
if (this.datasource.paginator) {
|
||||
this.datasource.paginator.firstPage();
|
||||
}
|
||||
}
|
||||
|
||||
getStatusOfTask(task: TaskEntityInfo) {
|
||||
return "green";
|
||||
}
|
||||
|
||||
deleteTask(deletedTask: TaskEntityInfo) {
|
||||
this.taskService.tasksTaskIDDelete(deletedTask.taskID).subscribe({
|
||||
next: resp => {
|
||||
if(resp.status == "success") {
|
||||
this.datasource.data = this.datasource.data.filter(task => task.taskID !== deletedTask.taskID);
|
||||
} else {
|
||||
this.snackbar.open("Unexpected behavior", "", {duration: 2000});
|
||||
}
|
||||
},
|
||||
error: err => {
|
||||
if(err.status == 403) {
|
||||
this.snackbar.open("No permission", "", {duration: 2000});
|
||||
} else if(err.status == 404) {
|
||||
this.snackbar.open("Task not found", "", {duration: 2000});
|
||||
} else {
|
||||
this.snackbar.open("Unexpected error", "", {duration: 2000});
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
editTask(task: TaskEntityInfo) {
|
||||
const taskEditorInfo: TaskEditorData = {
|
||||
task: task,
|
||||
taskgroupID: this.taskgroupID!
|
||||
};
|
||||
const dialogRef = this.dialog.open(TaskEditorComponent, {data: taskEditorInfo, minWidth: "400px"})
|
||||
}
|
||||
|
||||
clearTasks() {
|
||||
const clearTaskData: ClearTaskDialogData = {
|
||||
tasks: this.datasource.data,
|
||||
taskgroupID: this.taskgroupID!
|
||||
}
|
||||
const dialogRef = this.dialog.open(ClearTaskDialogComponent, {data: clearTaskData, width: "600px"});
|
||||
dialogRef.afterClosed().subscribe(res => {
|
||||
if(res != undefined) {
|
||||
this.datasource.data = this.datasource.data.filter(task => !res.includes(task));
|
||||
}
|
||||
})
|
||||
}
|
||||
addTask(task: TaskEntityInfo) {
|
||||
const data = this.datasource.data;
|
||||
data.push(task)
|
||||
this.datasource.data = data;
|
||||
}
|
||||
}
|
6
frontend/src/app/tasks/task-editor/TaskEditorData.ts
Normal file
6
frontend/src/app/tasks/task-editor/TaskEditorData.ts
Normal file
@ -0,0 +1,6 @@
|
||||
import {TaskEntityInfo} from "../../../api";
|
||||
|
||||
export interface TaskEditorData {
|
||||
taskgroupID: number;
|
||||
task: TaskEntityInfo | undefined
|
||||
}
|
15
frontend/src/app/tasks/task-editor/task-editor.component.css
Normal file
15
frontend/src/app/tasks/task-editor/task-editor.component.css
Normal file
@ -0,0 +1,15 @@
|
||||
.long-form {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.date-form {
|
||||
width: 49%;
|
||||
}
|
||||
#startDate {
|
||||
float: left;
|
||||
}
|
||||
|
||||
|
||||
#endDate {
|
||||
float: right;
|
||||
}
|
@ -0,0 +1,32 @@
|
||||
<h1 mat-dialog-title *ngIf="editorData.task != undefined">Edit Task ({{editorData.task!.taskName}})</h1>
|
||||
<h1 mat-dialog-title *ngIf="editorData.task == undefined">Create New Task</h1>
|
||||
<div mat-dialog-content>
|
||||
<mat-form-field appearance="outline" class="long-form">
|
||||
<mat-label>Name</mat-label>
|
||||
<input matInput [formControl]="nameCtrl">
|
||||
<mat-hint align="end">{{nameCtrl.value.length}} / 255</mat-hint>
|
||||
</mat-form-field>
|
||||
<mat-form-field appearance="outline" class="long-form">
|
||||
<mat-label>ETA</mat-label>
|
||||
<input matInput type="number" [formControl]="etaCtrl" min="0">
|
||||
</mat-form-field>
|
||||
<mat-form-field class="date-form" id="startDate">
|
||||
<mat-label>Startdate</mat-label>
|
||||
<input matInput [matDatepicker]="startpicker" [formControl]="startDate">
|
||||
<mat-hint>MM/DD/YYYY</mat-hint>
|
||||
<mat-datepicker-toggle matIconSuffix [for]="startpicker"></mat-datepicker-toggle>
|
||||
<mat-datepicker #startpicker></mat-datepicker>
|
||||
</mat-form-field>
|
||||
<mat-form-field class="date-form" id="endDate">
|
||||
<mat-label>Deadline</mat-label>
|
||||
<input matInput [matDatepicker]="deadlinepicker" [formControl]="endDate">
|
||||
<mat-hint>MM/DD/YYYY</mat-hint>
|
||||
<mat-datepicker-toggle matIconSuffix [for]="deadlinepicker"></mat-datepicker-toggle>
|
||||
<mat-datepicker #deadlinepicker></mat-datepicker>
|
||||
</mat-form-field>
|
||||
</div>
|
||||
|
||||
<div mat-dialog-actions align="end">
|
||||
<button mat-raised-button (click)="cancel()">Cancel</button>
|
||||
<button mat-raised-button color="primary" (click)="submit()">{{editorData.task == undefined? 'Add Task': 'Edit Task'}}</button>
|
||||
</div>
|
@ -0,0 +1,25 @@
|
||||
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
|
||||
import { TaskEditorComponent } from './task-editor.component';
|
||||
|
||||
describe('TaskEditorComponent', () => {
|
||||
let component: TaskEditorComponent;
|
||||
let fixture: ComponentFixture<TaskEditorComponent>;
|
||||
|
||||
beforeEach(async () => {
|
||||
await TestBed.configureTestingModule({
|
||||
declarations: [ TaskEditorComponent ]
|
||||
})
|
||||
.compileComponents();
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
fixture = TestBed.createComponent(TaskEditorComponent);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
101
frontend/src/app/tasks/task-editor/task-editor.component.ts
Normal file
101
frontend/src/app/tasks/task-editor/task-editor.component.ts
Normal file
@ -0,0 +1,101 @@
|
||||
import {Component, Inject, OnInit} from '@angular/core';
|
||||
import {FormControl, UntypedFormControl, Validators} from "@angular/forms";
|
||||
import * as _moment from 'moment';
|
||||
import {DateAdapter, MAT_DATE_FORMATS, MAT_DATE_LOCALE} from "@angular/material/core";
|
||||
import {MomentDateAdapter} from "@angular/material-moment-adapter";
|
||||
import {MAT_DIALOG_DATA, MatDialogRef} from "@angular/material/dialog";
|
||||
import {TaskService} from "../../../api";
|
||||
import {TaskEditorData} from "./TaskEditorData";
|
||||
import {MatSnackBar} from "@angular/material/snack-bar";
|
||||
|
||||
|
||||
@Component({
|
||||
selector: 'app-task-editor',
|
||||
templateUrl: './task-editor.component.html',
|
||||
styleUrls: ['./task-editor.component.css'],
|
||||
})
|
||||
export class TaskEditorComponent implements OnInit {
|
||||
|
||||
nameCtrl: FormControl = new FormControl('', [Validators.required, Validators.maxLength(255)])
|
||||
etaCtrl: FormControl = new FormControl(0, [Validators.required, Validators.min(0)])
|
||||
startDate: FormControl = new FormControl(Date.now(), [Validators.required])
|
||||
endDate: FormControl = new FormControl('');
|
||||
constructor(private dialog: MatDialogRef<TaskEditorComponent>,
|
||||
private taskService: TaskService,
|
||||
@Inject(MAT_DIALOG_DATA) public editorData: TaskEditorData,
|
||||
private snackbar: MatSnackBar) { }
|
||||
|
||||
ngOnInit(): void {
|
||||
if(this.editorData.task != undefined) {
|
||||
this.nameCtrl.setValue(this.editorData.task.taskName);
|
||||
this.etaCtrl.setValue(this.editorData.task.eta)
|
||||
this.startDate.setValue(this.editorData.task.startDate);
|
||||
this.endDate.setValue(this.editorData.task.deadline);
|
||||
}
|
||||
}
|
||||
|
||||
cancel() {
|
||||
this.dialog.close();
|
||||
}
|
||||
|
||||
submit() {
|
||||
|
||||
if(this.editorData.task != undefined) {
|
||||
this.editTask()
|
||||
} else {
|
||||
this.createTask();
|
||||
}
|
||||
}
|
||||
|
||||
createTask() {
|
||||
this.taskService.tasksTaskgroupIDPut(this.editorData.taskgroupID, {
|
||||
taskName: this.nameCtrl.value,
|
||||
eta: this.etaCtrl.value,
|
||||
startDate: this.startDate.value,
|
||||
deadline: this.endDate.value
|
||||
}).subscribe({
|
||||
next: resp => {
|
||||
this.dialog.close(resp);
|
||||
},
|
||||
error: err => {
|
||||
if(err.status == 403) {
|
||||
this.snackbar.open("No permission", "", {duration: 2000});
|
||||
} else if(err.status == 404) {
|
||||
this.snackbar.open("Taskgroup not found", "", {duration: 2000});
|
||||
} else if(err.status == 409) {
|
||||
this.snackbar.open("Task already exists", "", {duration: 2000});
|
||||
} else {
|
||||
this.snackbar.open("Unexpected error", "", {duration: 3000});
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
editTask() {
|
||||
this.taskService.tasksTaskIDPost(this.editorData.task!.taskID, {
|
||||
taskName: this.nameCtrl.value,
|
||||
eta: this.etaCtrl.value,
|
||||
startDate: this.startDate.value,
|
||||
deadline: this.endDate.value
|
||||
}).subscribe({
|
||||
next: resp => {
|
||||
this.editorData.task!.taskName = this.nameCtrl.value;
|
||||
this.editorData.task!.eta = this.etaCtrl.value;
|
||||
this.editorData.task!.startDate = this.startDate.value;
|
||||
this.editorData.task!.deadline = this.endDate.value;
|
||||
this.dialog.close(true);
|
||||
},
|
||||
error: err => {
|
||||
if(err.status == 403) {
|
||||
this.snackbar.open("No permission", "", {duration: 2000});
|
||||
} else if(err.status == 404) {
|
||||
this.snackbar.open("Taskgroup not found", "", {duration: 2000});
|
||||
} else if(err.status == 409) {
|
||||
this.snackbar.open("Task already exists", "", {duration: 2000});
|
||||
} else {
|
||||
this.snackbar.open("Unexpected error", "", {duration: 3000});
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
@ -1,7 +1,7 @@
|
||||
import { Component, OnInit } from '@angular/core';
|
||||
import {AbstractControl, FormControl, ValidationErrors, Validators} from "@angular/forms";
|
||||
import {AbstractControl, UntypedFormControl, ValidationErrors, Validators} from "@angular/forms";
|
||||
import {AccountService} from "../../../../api";
|
||||
import {MatSnackBar} from "@angular/material/snack-bar";
|
||||
import {MatSnackBar as MatSnackBar} from "@angular/material/snack-bar";
|
||||
|
||||
@Component({
|
||||
selector: 'app-change-password',
|
||||
@ -14,9 +14,9 @@ export class ChangePasswordComponent implements OnInit {
|
||||
|
||||
hide: boolean = true;
|
||||
pending: boolean = false;
|
||||
oldPasswordControl = new FormControl('', [Validators.required])
|
||||
newPasswordControl = new FormControl('', [Validators.required, Validators.minLength(6)])
|
||||
duplicatePasswordControl = new FormControl('', [
|
||||
oldPasswordControl = new UntypedFormControl('', [Validators.required])
|
||||
newPasswordControl = new UntypedFormControl('', [Validators.required, Validators.minLength(6)])
|
||||
duplicatePasswordControl = new UntypedFormControl('', [
|
||||
Validators.required,
|
||||
(control: AbstractControl): ValidationErrors | null => {
|
||||
return control.value != this.newPassword ? {duplicate: {value: control.value}} : null
|
||||
|
@ -1,9 +1,9 @@
|
||||
import { Component, OnInit } from '@angular/core';
|
||||
import {FormControl, Validators} from "@angular/forms";
|
||||
import {UntypedFormControl, Validators} from "@angular/forms";
|
||||
import {AccountService} from "../../../../api";
|
||||
import {Router} from "@angular/router";
|
||||
import {AuthService} from "../../../auth.service";
|
||||
import {MatSnackBar} from "@angular/material/snack-bar";
|
||||
import {MatSnackBar as MatSnackBar} from "@angular/material/snack-bar";
|
||||
|
||||
@Component({
|
||||
selector: 'app-delete-account',
|
||||
@ -14,7 +14,7 @@ export class DeleteAccountComponent implements OnInit {
|
||||
password: string = "";
|
||||
|
||||
hide: boolean = true;
|
||||
passwordControl = new FormControl('', [Validators.required]);
|
||||
passwordControl = new UntypedFormControl('', [Validators.required]);
|
||||
pending: boolean = false;
|
||||
|
||||
constructor(private accountService: AccountService, private router: Router, private auth: AuthService, private snackbar: MatSnackBar) { }
|
||||
|
@ -1,7 +1,7 @@
|
||||
import { Component, OnInit } from '@angular/core';
|
||||
import {AccountService} from "../../../../api";
|
||||
import {FormControl, Validators} from "@angular/forms";
|
||||
import {MatSnackBar} from "@angular/material/snack-bar";
|
||||
import {UntypedFormControl, Validators} from "@angular/forms";
|
||||
import {MatSnackBar as MatSnackBar} from "@angular/material/snack-bar";
|
||||
|
||||
@Component({
|
||||
selector: 'app-manage-email',
|
||||
@ -12,8 +12,8 @@ export class ManageEmailComponent implements OnInit {
|
||||
email : string = "";
|
||||
password: string = "";
|
||||
|
||||
emailControl = new FormControl('', [Validators.required, Validators.email]);
|
||||
passwordControl = new FormControl('', [Validators.required])
|
||||
emailControl = new UntypedFormControl('', [Validators.required, Validators.email]);
|
||||
passwordControl = new UntypedFormControl('', [Validators.required])
|
||||
hide: boolean = true;
|
||||
pending: boolean = false;
|
||||
|
||||
|
@ -7,20 +7,8 @@ import {
|
||||
platformBrowserDynamicTesting
|
||||
} from '@angular/platform-browser-dynamic/testing';
|
||||
|
||||
declare const require: {
|
||||
context(path: string, deep?: boolean, filter?: RegExp): {
|
||||
<T>(id: string): T;
|
||||
keys(): string[];
|
||||
};
|
||||
};
|
||||
|
||||
// First, initialize the Angular testing environment.
|
||||
getTestBed().initTestEnvironment(
|
||||
BrowserDynamicTestingModule,
|
||||
platformBrowserDynamicTesting(),
|
||||
);
|
||||
|
||||
// Then we find all the tests.
|
||||
const context = require.context('./', true, /\.spec\.ts$/);
|
||||
// And load the modules.
|
||||
context.keys().map(context);
|
||||
|
@ -2,7 +2,7 @@
|
||||
{
|
||||
"compileOnSave": false,
|
||||
"compilerOptions": {
|
||||
"baseUrl": "./",
|
||||
"baseUrl": "src",
|
||||
"outDir": "./dist/out-tsc",
|
||||
"forceConsistentCasingInFileNames": true,
|
||||
"strict": true,
|
||||
@ -16,12 +16,13 @@
|
||||
"experimentalDecorators": true,
|
||||
"moduleResolution": "node",
|
||||
"importHelpers": true,
|
||||
"target": "es2017",
|
||||
"target": "ES2022",
|
||||
"module": "es2020",
|
||||
"lib": [
|
||||
"es2020",
|
||||
"dom"
|
||||
]
|
||||
],
|
||||
"useDefineForClassFields": false
|
||||
},
|
||||
"angularCompilerOptions": {
|
||||
"enableI18nLegacyMessageIdFormat": false,
|
||||
|
402
openapi.yaml
402
openapi.yaml
@ -654,9 +654,8 @@ paths:
|
||||
content:
|
||||
'application/json':
|
||||
schema:
|
||||
type: array
|
||||
items:
|
||||
$ref: '#/components/schemas/TaskgroupEntityInfo'
|
||||
type: object
|
||||
$ref: '#/components/schemas/TaskgroupDetailInfo'
|
||||
403:
|
||||
description: No permission
|
||||
content:
|
||||
@ -829,6 +828,303 @@ paths:
|
||||
example: "failed"
|
||||
enum:
|
||||
- "failed"
|
||||
/taskgroups/{taskgroupID}/clear:
|
||||
delete:
|
||||
security:
|
||||
- API_TOKEN: []
|
||||
tags:
|
||||
- taskgroup
|
||||
summary: clears tasks
|
||||
description: Deletes all tasks of that taskgroup
|
||||
parameters:
|
||||
- name: taskgroupID
|
||||
in: path
|
||||
description: internal id of taskgroup
|
||||
required: true
|
||||
schema:
|
||||
type: number
|
||||
example: 1
|
||||
responses:
|
||||
200:
|
||||
description: Anfrage erfolgreich
|
||||
content:
|
||||
'application/json':
|
||||
schema:
|
||||
type: object
|
||||
$ref: "#/components/schemas/SimpleStatusResponse"
|
||||
403:
|
||||
description: No permission
|
||||
content:
|
||||
'application/json':
|
||||
schema:
|
||||
type: object
|
||||
$ref: "#/components/schemas/SimpleStatusResponse"
|
||||
404:
|
||||
description: Taskgroup does not exist
|
||||
content:
|
||||
'application/json':
|
||||
schema:
|
||||
type: object
|
||||
$ref: "#/components/schemas/SimpleStatusResponse"
|
||||
/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"
|
||||
/tasks/{taskID}:
|
||||
post:
|
||||
security:
|
||||
- API_TOKEN: []
|
||||
tags:
|
||||
- task
|
||||
summary: edits an existing task
|
||||
description: edits an existing task
|
||||
parameters:
|
||||
- name: taskID
|
||||
in: path
|
||||
description: internal id of task
|
||||
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"
|
||||
delete:
|
||||
security:
|
||||
- API_TOKEN: []
|
||||
tags:
|
||||
- task
|
||||
summary: edits an existing task
|
||||
description: edits an existing task
|
||||
parameters:
|
||||
- name: taskID
|
||||
in: path
|
||||
description: internal id of task
|
||||
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/SimpleStatusResponse"
|
||||
403:
|
||||
description: No permission
|
||||
content:
|
||||
'application/json':
|
||||
schema:
|
||||
type: object
|
||||
$ref: "#/components/schemas/SimpleStatusResponse"
|
||||
404:
|
||||
description: Taskgroup does not exist
|
||||
content:
|
||||
'application/json':
|
||||
schema:
|
||||
type: object
|
||||
$ref: "#/components/schemas/SimpleStatusResponse"
|
||||
|
||||
|
||||
|
||||
components:
|
||||
securitySchemes:
|
||||
API_TOKEN:
|
||||
@ -836,6 +1132,18 @@ components:
|
||||
scheme: bearer
|
||||
bearerFormat: JWT
|
||||
schemas:
|
||||
SimpleStatusResponse:
|
||||
required:
|
||||
- status
|
||||
additionalProperties: false
|
||||
properties:
|
||||
status:
|
||||
type: string
|
||||
description: Response Status der Request
|
||||
example: "failed"
|
||||
enum:
|
||||
- success
|
||||
- failed
|
||||
LoginRequest:
|
||||
required:
|
||||
- username
|
||||
@ -1019,7 +1327,6 @@ components:
|
||||
required:
|
||||
- taskgroupID
|
||||
- taskgroupName
|
||||
- parentTaskgroup
|
||||
additionalProperties: false
|
||||
properties:
|
||||
taskgroupID:
|
||||
@ -1032,9 +1339,6 @@ components:
|
||||
example: Taskgroup 1
|
||||
maxLength: 255
|
||||
minLength: 1
|
||||
parentTaskgroup:
|
||||
type: object
|
||||
$ref: '#/components/schemas/TaskgroupEntityInfo'
|
||||
TaskgroupFieldInfo:
|
||||
required:
|
||||
- name
|
||||
@ -1051,4 +1355,86 @@ components:
|
||||
type: number
|
||||
description: internal id of parent Taskgroup
|
||||
example: 1
|
||||
|
||||
TaskgroupDetailInfo:
|
||||
required:
|
||||
- children
|
||||
- ancestors
|
||||
- taskgroupInfo
|
||||
additionalProperties: false
|
||||
properties:
|
||||
children:
|
||||
type: array
|
||||
items:
|
||||
$ref: '#/components/schemas/TaskgroupEntityInfo'
|
||||
ancestors:
|
||||
type: array
|
||||
items:
|
||||
$ref: '#/components/schemas/TaskgroupEntityInfo'
|
||||
taskgroupInfo:
|
||||
type: object
|
||||
$ref: '#/components/schemas/TaskgroupEntityInfo'
|
||||
TaskEntityInfo:
|
||||
required:
|
||||
- taskID
|
||||
- taskName
|
||||
- eta
|
||||
- startDate
|
||||
- deadline
|
||||
- overdue
|
||||
- finished
|
||||
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
|
||||
finished:
|
||||
type: boolean
|
||||
description: determines whether the task is finished
|
||||
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
|
Loading…
Reference in New Issue
Block a user