diff --git a/backend/.idea/workspace.xml b/backend/.idea/workspace.xml index e461dea..8976ff7 100644 --- a/backend/.idea/workspace.xml +++ b/backend/.idea/workspace.xml @@ -4,8 +4,8 @@ - - + + @@ -41,33 +41,34 @@ - { - "keyToString": { - "RequestMappingsPanelOrder0": "0", - "RequestMappingsPanelOrder1": "1", - "RequestMappingsPanelWidth0": "75", - "RequestMappingsPanelWidth1": "75", - "RunOnceActivity.OpenProjectViewOnStart": "true", - "RunOnceActivity.ShowReadmeOnStart": "true", - "WebServerToolWindowFactoryState": "false", - "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)", - "nodejs_package_manager_path": "npm", - "settings.editor.selected.configurable": "swagger", - "ts.external.directory.path": "/snap/intellij-idea-ultimate/459/plugins/javascript-impl/jsLanguageServicesImpl/external", - "vue.rearranger.settings.migration": "true" + +}]]> @@ -258,7 +259,15 @@ 1698573369764 - + + + 1698592265846 + + + + 1698592265846 + + @@ -285,7 +294,8 @@ - + + diff --git a/backend/src/main/java/core/api/controller/TaskController.java b/backend/src/main/java/core/api/controller/TaskController.java index 5be2520..342640a 100644 --- a/backend/src/main/java/core/api/controller/TaskController.java +++ b/backend/src/main/java/core/api/controller/TaskController.java @@ -2,9 +2,7 @@ package core.api.controller; import core.api.models.auth.SimpleStatusResponse; import core.api.models.timemanager.taskSchedule.ScheduleInfo; -import core.api.models.timemanager.tasks.TaskEntityInfo; -import core.api.models.timemanager.tasks.TaskFieldInfo; -import core.api.models.timemanager.tasks.TaskShortInfo; +import core.api.models.timemanager.tasks.*; import core.entities.timemanager.Task; import core.entities.timemanager.Taskgroup; import core.services.*; @@ -31,22 +29,37 @@ public class TaskController { this.taskgroupService = taskgroupService; } - @GetMapping("/tasks/all/{finished}") - public ResponseEntity> loadAllTasks(@PathVariable boolean finished) { - List taskList = taskService.loadAllTasks(SecurityContextHolder.getContext().getAuthentication().getName(), finished); + @GetMapping("/tasks/all/{scope}/{detailed}") + public ResponseEntity> loadAllTasksShort(@PathVariable TaskScope scope, @PathVariable boolean detailed) { + List taskList = taskService.loadAllTasks(SecurityContextHolder.getContext().getAuthentication().getName(), scope); List taskShortInfos = new ArrayList<>(); + List taskInfos = new ArrayList<>(); for(Task task : taskList) { - List ancestors = Taskgroup.getAncestorList(task.getTaskgroup()); - ancestors.add(task.getTaskgroup()); - StringBuilder builder = new StringBuilder(); - for(Taskgroup taskgroup : ancestors) { - builder.append(taskgroup.getTaskgroupName()).append("/"); + StringBuilder builder = loadTaskgroupPath(task); + if(!detailed) { + taskShortInfos.add(new TaskShortInfo(task.getTaskID(), builder.toString())); + } else { + taskInfos.add(new TaskTaskgroupInfo(task)); } - builder.append(task.getTaskName()); - taskShortInfos.add(new TaskShortInfo(task.getTaskID(), builder.toString())); } - return ResponseEntity.ok(taskShortInfos); + + if(detailed) { + return ResponseEntity.ok(taskInfos); + } else { + return ResponseEntity.ok(taskShortInfos); + } + } + + private StringBuilder loadTaskgroupPath(Task task) { + List ancestors = Taskgroup.getAncestorList(task.getTaskgroup()); + ancestors.add(task.getTaskgroup()); + StringBuilder builder = new StringBuilder(); + for(Taskgroup taskgroup : ancestors) { + builder.append(taskgroup.getTaskgroupName()).append("/"); + } + builder.append(task.getTaskName()); + return builder; } @GetMapping("/tasks/{taskgroupID}/{status}") diff --git a/backend/src/main/java/core/api/models/timemanager/tasks/TaskScope.java b/backend/src/main/java/core/api/models/timemanager/tasks/TaskScope.java new file mode 100644 index 0000000..8a5dd02 --- /dev/null +++ b/backend/src/main/java/core/api/models/timemanager/tasks/TaskScope.java @@ -0,0 +1,8 @@ +package core.api.models.timemanager.tasks; + +public enum TaskScope { + + FINISHED, + UNFINISHED, + OVERDUE; +} diff --git a/backend/src/main/java/core/api/models/timemanager/tasks/TaskTaskgroupInfo.java b/backend/src/main/java/core/api/models/timemanager/tasks/TaskTaskgroupInfo.java new file mode 100644 index 0000000..b46e438 --- /dev/null +++ b/backend/src/main/java/core/api/models/timemanager/tasks/TaskTaskgroupInfo.java @@ -0,0 +1,118 @@ +package core.api.models.timemanager.tasks; + +import core.api.models.timemanager.taskgroup.TaskgroupEntityInfo; +import core.entities.timemanager.Task; +import core.entities.timemanager.Taskgroup; + +import java.time.LocalDate; +import java.util.ArrayList; +import java.util.List; + +public class TaskTaskgroupInfo { + + private long taskID; + private String taskName; + + private int eta; + + private LocalDate startDate; + + private LocalDate deadline; + + private boolean overdue; + + private boolean finished; + + private int workTime; + + private List taskgroups; + + public TaskTaskgroupInfo(Task task) { + this.taskID = task.getTaskID(); + this.taskName = task.getTaskName(); + this.eta = task.getEta(); + this.startDate = task.getStartDate(); + this.deadline = task.getDeadline(); + if(task.getDeadline() != null) { + this.overdue = LocalDate.now().isAfter(task.getDeadline()); + } + this.finished = task.isFinished(); + this.workTime = task.getWorkTime(); + + List taskgroupList = Taskgroup.getAncestorList(task.getTaskgroup()); + taskgroupList.add(task.getTaskgroup()); + this.taskgroups = taskgroupList.stream().map(TaskgroupEntityInfo::new).toList(); + } + + 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; + } + + public int getWorkTime() { + return workTime; + } + + public void setWorkTime(int workTime) { + this.workTime = workTime; + } + + public List getTaskgroups() { + return taskgroups; + } + + public void setTaskgroups(List taskgroups) { + this.taskgroups = taskgroups; + } +} diff --git a/backend/src/main/java/core/repositories/timemanager/TaskRepository.java b/backend/src/main/java/core/repositories/timemanager/TaskRepository.java index 59f3fe4..9764f60 100644 --- a/backend/src/main/java/core/repositories/timemanager/TaskRepository.java +++ b/backend/src/main/java/core/repositories/timemanager/TaskRepository.java @@ -8,6 +8,7 @@ import org.springframework.data.repository.CrudRepository; import org.springframework.stereotype.Repository; import javax.transaction.Transactional; +import java.time.LocalDate; import java.util.List; @Repository @@ -25,4 +26,7 @@ public interface TaskRepository extends CrudRepository { @Modifying @Query(value = "DELETE FROM Task t WHERE t.taskID = ?1") void deleteByTaskID(long taskID); + + @Query(value = "SELECT t FROM Task t WHERE t.taskgroup.user.username = ?1 AND t.deadline is NOT NULL AND t.deadline > ?2 AND t.finished = FALSE") + List findAllOverdue(String username, LocalDate now); } diff --git a/backend/src/main/java/core/services/TaskService.java b/backend/src/main/java/core/services/TaskService.java index 7a300fa..d55a9e4 100644 --- a/backend/src/main/java/core/services/TaskService.java +++ b/backend/src/main/java/core/services/TaskService.java @@ -1,6 +1,7 @@ package core.services; import core.api.models.timemanager.tasks.TaskFieldInfo; +import core.api.models.timemanager.tasks.TaskScope; import core.entities.timemanager.BasicTaskSchedule; import core.entities.timemanager.Task; import core.entities.timemanager.Taskgroup; @@ -10,6 +11,7 @@ import core.repositories.timemanager.TaskgroupRepository; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; +import java.time.LocalDate; import java.time.LocalDateTime; import java.util.*; @@ -99,7 +101,18 @@ public class TaskService { } } - public List loadAllTasks(String username, boolean finished) { - return taskRepository.findAllByUser(username, finished); + public List loadAllTasks(String username, TaskScope scope) { + switch (scope) { + case UNFINISHED, FINISHED -> { + return taskRepository.findAllByUser(username, scope.equals(TaskScope.FINISHED)); + } + case OVERDUE -> { + return taskRepository.findAllOverdue(username, LocalDate.now()); + } + default -> { + return new ArrayList<>(); + } + } + } } diff --git a/frontend/src/api/.openapi-generator/FILES b/frontend/src/api/.openapi-generator/FILES index e0272ae..51b9f45 100644 --- a/frontend/src/api/.openapi-generator/FILES +++ b/frontend/src/api/.openapi-generator/FILES @@ -40,6 +40,7 @@ model/taskFieldInfo.ts model/taskOverviewInfo.ts model/taskScheduleStopResponse.ts model/taskShortInfo.ts +model/taskTaskgroupInfo.ts model/taskgroupDetailInfo.ts model/taskgroupEntityInfo.ts model/taskgroupFieldInfo.ts diff --git a/frontend/src/api/api/task.service.ts b/frontend/src/api/api/task.service.ts index 549949d..c523119 100644 --- a/frontend/src/api/api/task.service.ts +++ b/frontend/src/api/api/task.service.ts @@ -23,6 +23,7 @@ import { SimpleStatusResponse } from '../model/models'; import { TaskEntityInfo } from '../model/models'; import { TaskFieldInfo } from '../model/models'; import { TaskShortInfo } from '../model/models'; +import { TaskTaskgroupInfo } from '../model/models'; import { BASE_PATH, COLLECTION_FORMATS } from '../variables'; import { Configuration } from '../configuration'; @@ -92,16 +93,20 @@ export class TaskService { /** * edits an existing task * edits an existing task - * @param finished fetches either finished or unfinished tasks + * @param scope defines scope of fetched tasks + * @param detailed determines whether an detailed response is required or not * @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 tasksAllFinishedGet(finished: boolean, observe?: 'body', reportProgress?: boolean, options?: {httpHeaderAccept?: 'application/json', context?: HttpContext}): Observable>; - public tasksAllFinishedGet(finished: boolean, observe?: 'response', reportProgress?: boolean, options?: {httpHeaderAccept?: 'application/json', context?: HttpContext}): Observable>>; - public tasksAllFinishedGet(finished: boolean, observe?: 'events', reportProgress?: boolean, options?: {httpHeaderAccept?: 'application/json', context?: HttpContext}): Observable>>; - public tasksAllFinishedGet(finished: boolean, observe: any = 'body', reportProgress: boolean = false, options?: {httpHeaderAccept?: 'application/json', context?: HttpContext}): Observable { - if (finished === null || finished === undefined) { - throw new Error('Required parameter finished was null or undefined when calling tasksAllFinishedGet.'); + public tasksAllScopeDetailedGet(scope: 'FINISHED' | 'UNFINISHED' | 'OVERDUE', detailed: boolean, observe?: 'body', reportProgress?: boolean, options?: {httpHeaderAccept?: 'application/json', context?: HttpContext}): Observable | Array>; + public tasksAllScopeDetailedGet(scope: 'FINISHED' | 'UNFINISHED' | 'OVERDUE', detailed: boolean, observe?: 'response', reportProgress?: boolean, options?: {httpHeaderAccept?: 'application/json', context?: HttpContext}): Observable | Array>>; + public tasksAllScopeDetailedGet(scope: 'FINISHED' | 'UNFINISHED' | 'OVERDUE', detailed: boolean, observe?: 'events', reportProgress?: boolean, options?: {httpHeaderAccept?: 'application/json', context?: HttpContext}): Observable | Array>>; + public tasksAllScopeDetailedGet(scope: 'FINISHED' | 'UNFINISHED' | 'OVERDUE', detailed: boolean, observe: any = 'body', reportProgress: boolean = false, options?: {httpHeaderAccept?: 'application/json', context?: HttpContext}): Observable { + if (scope === null || scope === undefined) { + throw new Error('Required parameter scope was null or undefined when calling tasksAllScopeDetailedGet.'); + } + if (detailed === null || detailed === undefined) { + throw new Error('Required parameter detailed was null or undefined when calling tasksAllScopeDetailedGet.'); } let localVarHeaders = this.defaultHeaders; @@ -136,7 +141,7 @@ export class TaskService { responseType_ = 'text'; } - return this.httpClient.get>(`${this.configuration.basePath}/tasks/all/${encodeURIComponent(String(finished))}`, + return this.httpClient.get | Array>(`${this.configuration.basePath}/tasks/all/${encodeURIComponent(String(scope))}/${encodeURIComponent(String(detailed))}`, { context: localVarHttpContext, responseType: responseType_, diff --git a/frontend/src/api/model/models.ts b/frontend/src/api/model/models.ts index 030f3a8..0515444 100644 --- a/frontend/src/api/model/models.ts +++ b/frontend/src/api/model/models.ts @@ -24,6 +24,7 @@ export * from './taskFieldInfo'; export * from './taskOverviewInfo'; export * from './taskScheduleStopResponse'; export * from './taskShortInfo'; +export * from './taskTaskgroupInfo'; export * from './taskgroupDetailInfo'; export * from './taskgroupEntityInfo'; export * from './taskgroupFieldInfo'; diff --git a/frontend/src/api/model/taskTaskgroupInfo.ts b/frontend/src/api/model/taskTaskgroupInfo.ts new file mode 100644 index 0000000..30743f1 --- /dev/null +++ b/frontend/src/api/model/taskTaskgroupInfo.ts @@ -0,0 +1,50 @@ +/** + * 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 TaskTaskgroupInfo { + /** + * 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; + /** + * number in minutes that was already worked on this task + */ + workTime: number; + taskgroups: Array; +} + diff --git a/frontend/src/app/app-routing.module.ts b/frontend/src/app/app-routing.module.ts index 66a658a..374891d 100644 --- a/frontend/src/app/app-routing.module.ts +++ b/frontend/src/app/app-routing.module.ts @@ -8,6 +8,7 @@ import {TaskgroupDashboardComponent} from "./taskgroups/taskgroup-dashboard/task import {TaskDetailOverviewComponent} from "./tasks/task-detail-overview/task-detail-overview.component"; import {SchedulerComponent} from "./schedules/scheduler/scheduler.component"; import {MissedSchedulesComponent} from "./missed-schedules/missed-schedules.component"; +import {OverdueTaskOverviewComponent} from "./overdue-task-overview/overdue-task-overview.component"; const routes: Routes = [ {path: '', component: MainComponent}, @@ -18,7 +19,8 @@ const routes: Routes = [ {path: 'taskgroups/:taskgroupID/tasks/:taskID', component: TaskDetailOverviewComponent}, {path: 'taskgroups/:taskgroupID/tasks/:taskID/schedule', component: SchedulerComponent}, {path: 'taskgroups/:taskgroupID/tasks/:taskID/schedule/:scheduleID', component: SchedulerComponent}, - {path: 'reschedule', component: MissedSchedulesComponent} + {path: 'reschedule', component: MissedSchedulesComponent}, + {path: 'overdue', component: OverdueTaskOverviewComponent} ]; @NgModule({ diff --git a/frontend/src/app/app.component.html b/frontend/src/app/app.component.html index e37af02..375a529 100644 --- a/frontend/src/app/app.component.html +++ b/frontend/src/app/app.component.html @@ -4,6 +4,7 @@ Organize ▾ Taskgroups + Overdue Tasks Missed Schedules diff --git a/frontend/src/app/app.module.ts b/frontend/src/app/app.module.ts index 8bf5716..e1b297e 100644 --- a/frontend/src/app/app.module.ts +++ b/frontend/src/app/app.module.ts @@ -71,6 +71,7 @@ import { ForgottenTaskStartDialogComponent } from './dashboard/forgotten-task-st import {MatAutocompleteModule} from "@angular/material/autocomplete"; import { MissedSchedulesComponent } from './missed-schedules/missed-schedules.component'; import { MissedScheduleForgetConfirmationDialogComponent } from './missed-schedules/missed-schedule-forget-confirmation-dialog/missed-schedule-forget-confirmation-dialog.component'; +import { OverdueTaskOverviewComponent } from './overdue-task-overview/overdue-task-overview.component'; @NgModule({ declarations: [ AppComponent, @@ -104,7 +105,8 @@ import { MissedScheduleForgetConfirmationDialogComponent } from './missed-schedu TaskOverviewComponent, ForgottenTaskStartDialogComponent, MissedSchedulesComponent, - MissedScheduleForgetConfirmationDialogComponent + MissedScheduleForgetConfirmationDialogComponent, + OverdueTaskOverviewComponent ], imports: [ BrowserModule, diff --git a/frontend/src/app/dashboard/forgotten-task-start-dialog/forgotten-task-start-dialog.component.ts b/frontend/src/app/dashboard/forgotten-task-start-dialog/forgotten-task-start-dialog.component.ts index 5cc7abf..81d8078 100644 --- a/frontend/src/app/dashboard/forgotten-task-start-dialog/forgotten-task-start-dialog.component.ts +++ b/frontend/src/app/dashboard/forgotten-task-start-dialog/forgotten-task-start-dialog.component.ts @@ -30,7 +30,7 @@ export class ForgottenTaskStartDialogComponent implements OnInit{ } ngOnInit() { - this.taskService.tasksAllFinishedGet(false).subscribe({ + this.taskService.tasksAllScopeDetailedGet("UNFINISHED", false).subscribe({ next: resp => { this.tasks = resp; this.filteredOptions = this.myControl.valueChanges.pipe( diff --git a/frontend/src/app/overdue-task-overview/overdue-task-overview.component.css b/frontend/src/app/overdue-task-overview/overdue-task-overview.component.css new file mode 100644 index 0000000..9c4e31d --- /dev/null +++ b/frontend/src/app/overdue-task-overview/overdue-task-overview.component.css @@ -0,0 +1,72 @@ +.container { + margin: 20px auto; + width: 70%; +} + +.spacer { + margin-bottom: 2.5%; +} + + +@media screen and (max-width: 600px) { + .container { + width: 100%; + margin: 20px 10px; + } +} + + +.undecorated-link { + text-decoration: none; + color: black; +} + +.undecorated-link:hover { + color: #3498db; +} + +.originally-planned-container { + border-style: solid; + border-color: #e1e1e1; + border-width: 1px; + margin-top: 10px; + border-radius: 5px; + padding: 10px; + +} + +.reschedule-actions-container { + display: flex; + justify-content: space-between; + flex-direction: row; +} + +.btn-group { + display: inline-block; +} + + +.yellowBtn { + background-color: #f39c12; + color: white; + border-radius: 0; +} + +.greenBtn { + background-color: #00bc8c; + color: white; +} + +.btn-group-item { + border-radius: 0; +} + +.btn-group-itemleft { + border-top-right-radius: 0; + border-bottom-right-radius: 0; +} + +.btn-group-itemright { + border-bottom-left-radius: 0; + border-top-left-radius: 0; +} diff --git a/frontend/src/app/overdue-task-overview/overdue-task-overview.component.html b/frontend/src/app/overdue-task-overview/overdue-task-overview.component.html new file mode 100644 index 0000000..9fd9445 --- /dev/null +++ b/frontend/src/app/overdue-task-overview/overdue-task-overview.component.html @@ -0,0 +1,29 @@ + + + + + + + {{taskgroup.taskgroupName}}/ + + {{task.taskName}} + + + + + Limit: {{task.deadline}} + + + + Schedule + Start now + Finish + + + deleteDelete + + + + + + diff --git a/frontend/src/app/overdue-task-overview/overdue-task-overview.component.spec.ts b/frontend/src/app/overdue-task-overview/overdue-task-overview.component.spec.ts new file mode 100644 index 0000000..a3ebca3 --- /dev/null +++ b/frontend/src/app/overdue-task-overview/overdue-task-overview.component.spec.ts @@ -0,0 +1,21 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { OverdueTaskOverviewComponent } from './overdue-task-overview.component'; + +describe('OverdueTaskOverviewComponent', () => { + let component: OverdueTaskOverviewComponent; + let fixture: ComponentFixture; + + beforeEach(() => { + TestBed.configureTestingModule({ + declarations: [OverdueTaskOverviewComponent] + }); + fixture = TestBed.createComponent(OverdueTaskOverviewComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/frontend/src/app/overdue-task-overview/overdue-task-overview.component.ts b/frontend/src/app/overdue-task-overview/overdue-task-overview.component.ts new file mode 100644 index 0000000..01f089c --- /dev/null +++ b/frontend/src/app/overdue-task-overview/overdue-task-overview.component.ts @@ -0,0 +1,98 @@ +import {Component, OnInit} from '@angular/core'; +import {ScheduleService, TaskEntityInfo, TaskService, TaskShortInfo, TaskTaskgroupInfo} from "../../api"; +import {NavigationLink} from "../navigation-link-list/navigation-link-list.component"; +import {Router} from "@angular/router"; +import {MatSnackBar} from "@angular/material/snack-bar"; + +@Component({ + selector: 'app-overdue-task-overview', + templateUrl: './overdue-task-overview.component.html', + styleUrls: ['./overdue-task-overview.component.css'] +}) +export class OverdueTaskOverviewComponent implements OnInit{ + + overdueTasks: TaskTaskgroupInfo[] = [] + defaultNavigationLinkPath: NavigationLink[] = [ + { + linkText: "Dashboard", + routerLink: ['/'] + }, + { + linkText: "Overdue Tasks", + routerLink: ["/overdue"] + } + ] + constructor(private taskService: TaskService, + private scheduleService: ScheduleService, + private router: Router, + private snackbar: MatSnackBar) { + + } + + ngOnInit() { + this.taskService.tasksAllScopeDetailedGet("OVERDUE", true).subscribe({ + next: resp => { + this.overdueTasks = resp as TaskTaskgroupInfo[]; + } + }) + } + + calcProgress(task: TaskTaskgroupInfo): number { + console.log(task.workTime / task.eta * 100) + return task.workTime / task.eta * 100 + } + startNow(task: TaskTaskgroupInfo) { + this.scheduleService.schedulesTaskIDNowPost(task.taskID).subscribe({ + next: resp => { + this.router.navigateByUrl("/"); + }, + error: err => { + if(err.status == 403) { + this.snackbar.open("No permissions", "", {duration: 2000}); + } else if(err.status == 404) { + this.snackbar.open("Not found", "", {duration: 2000}); + } else if(err.status == 409) { + this.snackbar.open("Task already running", "", {duration: 2000}); + } else { + this.snackbar.open("Unexpected error", "", {duration: 2000}); + } + } + }) + } + + finishTask(task: TaskTaskgroupInfo) { + this.taskService.tasksTaskIDFinishPost(task.taskID).subscribe({ + next: resp => { + this.overdueTasks = this.overdueTasks.filter(t => t.taskID !== task.taskID) + }, + error: err => { + if(err.status == 403) { + this.snackbar.open("No permissions", "", {duration: 2000}); + } else if(err.status == 404) { + this.snackbar.open("Not found", "", {duration: 2000}); + } else { + this.snackbar.open("Unexpected error", "", {duration: 2000}); + } + } + }) + } + + deleteTask(deletedTask: TaskTaskgroupInfo) { + this.taskService.tasksTaskIDDelete(deletedTask.taskID).subscribe({ + next: resp => { + this.overdueTasks = this.overdueTasks.filter(task => task.taskID !== deletedTask.taskID); + }, + error: err => { + if(err.status == 403) { + this.snackbar.open("No permissions", "", {duration: 2000}); + } else if(err.status == 404) { + this.snackbar.open("Not found", "", {duration: 2000}); + } else { + this.snackbar.open("Unexpected error", "", {duration: 2000}); + } + } + }) + } + + +} diff --git a/openapi.yaml b/openapi.yaml index 0f59d2e..8eaa491 100644 --- a/openapi.yaml +++ b/openapi.yaml @@ -883,7 +883,7 @@ paths: schema: type: object $ref: "#/components/schemas/SimpleStatusResponse" - /tasks/all/{finished}: + /tasks/all/{scope}/{detailed}: get: security: - API_TOKEN: [] @@ -892,11 +892,21 @@ paths: summary: edits an existing task description: edits an existing task parameters: - - name: finished + - name: scope in: path - description: fetches either finished or unfinished tasks + description: defines scope of fetched tasks required: true schema: + type: string + enum: + - FINISHED + - UNFINISHED + - OVERDUE + - name: detailed + in: path + description: determines whether an detailed response is required or not + required: true + schema: type: boolean example: true responses: @@ -905,9 +915,14 @@ paths: content: application/json: schema: - type: array - items: - $ref: '#/components/schemas/TaskShortInfo' + oneOf: + - type: array + items: + $ref: '#/components/schemas/TaskShortInfo' + - type: array + items: + $ref: '#/components/schemas/TaskTaskgroupInfo' + /tasks/{taskgroupID}/{status}: get: @@ -2048,6 +2063,56 @@ components: type: number description: number in minutes that was already worked on this task example: 10 + TaskTaskgroupInfo: + required: + - taskID + - taskName + - eta + - startDate + - deadline + - overdue + - finished + - workTime + - taskgroups + 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 + workTime: + type: number + description: number in minutes that was already worked on this task + example: 10 + taskgroups: + type: array + items: + $ref: '#/components/schemas/TaskgroupEntityInfo' TaskFieldInfo: required: - taskName
Limit: {{task.deadline}}