From ac9e4c0f942640979884caac6e50cc35f22518d4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20B=C3=B6ckelmann?= Date: Sat, 18 Nov 2023 17:59:13 +0100 Subject: [PATCH 1/3] Register forgotten Schedule --- .../taskSchedule/ForgottenScheduleInfo.java | 4 + frontend/src/app/app-routing.module.ts | 6 +- .../active-schedule.component.html | 2 +- .../forgotten-task-start-dialog.component.css | 53 +++++- ...forgotten-task-start-dialog.component.html | 74 +++++--- .../forgotten-task-start-dialog.component.ts | 162 +++++++++++++----- 6 files changed, 221 insertions(+), 80 deletions(-) diff --git a/backend/src/main/java/core/api/models/timemanager/taskSchedule/ForgottenScheduleInfo.java b/backend/src/main/java/core/api/models/timemanager/taskSchedule/ForgottenScheduleInfo.java index b885ee6..c844883 100644 --- a/backend/src/main/java/core/api/models/timemanager/taskSchedule/ForgottenScheduleInfo.java +++ b/backend/src/main/java/core/api/models/timemanager/taskSchedule/ForgottenScheduleInfo.java @@ -1,5 +1,7 @@ package core.api.models.timemanager.taskSchedule; +import com.fasterxml.jackson.annotation.JsonFormat; + import javax.validation.constraints.NotNull; import java.time.LocalDate; import java.time.LocalDateTime; @@ -7,9 +9,11 @@ import java.time.LocalDateTime; public class ForgottenScheduleInfo { @NotNull + @JsonFormat(pattern = "yyyy-MM-dd'T'HH:mm:ss.SSSXXX") private LocalDateTime startTime; @NotNull + @JsonFormat(pattern = "yyyy-MM-dd'T'HH:mm:ss.SSSXXX") private LocalDateTime endTime; public ForgottenScheduleInfo(LocalDateTime startTime, LocalDateTime endTime) { diff --git a/frontend/src/app/app-routing.module.ts b/frontend/src/app/app-routing.module.ts index 31b612f..540fa74 100644 --- a/frontend/src/app/app-routing.module.ts +++ b/frontend/src/app/app-routing.module.ts @@ -12,6 +12,9 @@ import {OverdueTaskOverviewComponent} from "./overdue-task-overview/overdue-task import {UpcomingTaskOverviewComponent} from "./upcoming-task-overview/upcoming-task-overview.component"; import {ActiveTaskOverviewComponent} from "./active-task-overview/active-task-overview.component"; import {DraggableSchedulerComponent} from "./schedules/draggable-scheduler/draggable-scheduler.component"; +import { + ForgottenTaskStartDialogComponent +} from "./dashboard/forgotten-task-start-dialog/forgotten-task-start-dialog.component"; const routes: Routes = [ {path: '', component: MainComponent}, @@ -26,7 +29,8 @@ const routes: Routes = [ {path: 'overdue', component: OverdueTaskOverviewComponent}, {path: 'upcoming', component: UpcomingTaskOverviewComponent}, {path: 'active', component: ActiveTaskOverviewComponent}, - {path: 'scheduler', component: DraggableSchedulerComponent} + {path: 'scheduler', component: DraggableSchedulerComponent}, + {path: 'forgotten', component: ForgottenTaskStartDialogComponent} ]; @NgModule({ diff --git a/frontend/src/app/dashboard/active-schedule/active-schedule.component.html b/frontend/src/app/dashboard/active-schedule/active-schedule.component.html index ff04003..2e1b983 100644 --- a/frontend/src/app/dashboard/active-schedule/active-schedule.component.html +++ b/frontend/src/app/dashboard/active-schedule/active-schedule.component.html @@ -1,7 +1,7 @@

Currently there is no task in progress.

- Did you forget to start an activity? + Did you forget to start an activity?
diff --git a/frontend/src/app/dashboard/forgotten-task-start-dialog/forgotten-task-start-dialog.component.css b/frontend/src/app/dashboard/forgotten-task-start-dialog/forgotten-task-start-dialog.component.css index ad2c300..240434b 100644 --- a/frontend/src/app/dashboard/forgotten-task-start-dialog/forgotten-task-start-dialog.component.css +++ b/frontend/src/app/dashboard/forgotten-task-start-dialog/forgotten-task-start-dialog.component.css @@ -1,4 +1,51 @@ -.example-full-width { - width: 100%; - margin-left: 10px; +.container { + margin: 20px auto; + width: 80%; + display: flex; + justify-content: space-between; } + +.spacer { + margin-bottom: 2.5%; +} + +::ng-deep .cal-week-view .cal-time-events { + max-height: 500px !important; + overflow-y: auto; +} + +@media screen and (max-width: 600px) { + .container { + width: 100%; + margin: 20px 10px; + } +} + +.calendar-container { + width: 75%; +} + +.task-container { + width: 23%; +} + +::ng-deep .mat-mdc-list-base { + --mdc-list-list-item-label-text-color: black +} + +::ng-deep .mat-mdc-list-base .taskgroup-btn, ::ng-deep .mat-mdc-list-base .taskgroup-last-btn { + --mdc-list-list-item-label-text-color: black +} + +.task-card { + background-color: #f3f3f3; + border: 0; + line-height: 4em; +} + + +.lightBlueBtn { + background-color: #3498db; + color: white; +} + diff --git a/frontend/src/app/dashboard/forgotten-task-start-dialog/forgotten-task-start-dialog.component.html b/frontend/src/app/dashboard/forgotten-task-start-dialog/forgotten-task-start-dialog.component.html index f1918e1..791f57b 100644 --- a/frontend/src/app/dashboard/forgotten-task-start-dialog/forgotten-task-start-dialog.component.html +++ b/frontend/src/app/dashboard/forgotten-task-start-dialog/forgotten-task-start-dialog.component.html @@ -1,31 +1,49 @@ -

Register forgotten activity

-
- - Number - - - - {{option}} - - - +
+
+

Register forgotten activity

+ + +
+ +
+
+ + +
+
+ + + +
+ +
+ +
+ +
+ + - Automatic starttime based on last schedule - Automatic starttime based on planned schedule - - Minutes spent - -
- -
- - -
- - 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 a2d601b..dadc140 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 @@ -1,76 +1,144 @@ import {Component, OnInit} from '@angular/core'; -import {ForgottenActivityRequest, ScheduleService, TaskService, TaskShortInfo} from "../../../api"; +import { + ForgottenActivityRequest, + ScheduleService, + TaskgroupEntityInfo, + TaskOverviewInfo, + TaskService, + TaskShortInfo +} from "../../../api"; import {MatSnackBar} from "@angular/material/snack-bar"; import {DialogRef} from "@angular/cdk/dialog"; import {MatDialogRef} from "@angular/material/dialog"; -import {filter, map, Observable, startWith} from "rxjs"; +import {filter, map, Observable, startWith, Subject} from "rxjs"; import {FormControl} from "@angular/forms"; +import {CalendarEvent, CalendarEventTimesChangedEvent} from "angular-calendar"; +import * as moment from "moment/moment"; +import {EventColor} from "calendar-utils"; +import {TaskOverviewData} from "../taskgroup-overview/taskgroup-overview.component"; +import {Router} from "@angular/router"; + +const colors: Record = { + red: { + primary: '#ad2121', + secondary: '#FAE3E3', + }, + blue: { + primary: '#1e90ff', + secondary: '#D1E8FF', + }, + yellow: { + primary: '#e3bc08', + secondary: '#FDF1BA', + }, +}; @Component({ selector: 'app-forgotten-task-start-dialog', templateUrl: './forgotten-task-start-dialog.component.html', styleUrls: ['./forgotten-task-start-dialog.component.css'] }) export class ForgottenTaskStartDialogComponent implements OnInit{ - - tasks: TaskShortInfo[] = [] myControl: FormControl = new FormControl(''); filteredOptions: Observable | undefined; + viewDate: Date = new Date(); + events: CalendarEvent[] = []; + refresh = new Subject(); + lastSchedule: boolean = false plannedSchedule: boolean = false minutesSpentControl: FormControl = new FormControl(); + tasks: CalendarEvent[] = []; + taskgroupID: number | undefined - constructor(private taskService: TaskService, - private snackbar: MatSnackBar, - private dialogRef: MatDialogRef, + taskgroupSelected: boolean = false; + + + constructor(private router: Router, private scheduleService: ScheduleService) { } ngOnInit() { - this.taskService.tasksAllScopeDetailedGet("UNFINISHED", false).subscribe({ + + } + + + externalDrop(event: CalendarEvent) { + if (this.events.indexOf(event) === -1) { + this.events = this.events.filter((iEvent) => iEvent !== event); + this.events.push(event); + } + } + + eventDropped({ + event, + newStart, + newEnd, + allDay, + }: CalendarEventTimesChangedEvent): void { + const externalIndex = this.tasks.indexOf(event); + if (typeof allDay !== 'undefined') { + event.allDay = allDay; + } + if (externalIndex > -1) { + this.tasks.splice(externalIndex, 1); + this.events.push(event); + this.taskgroupSelected = true; + } + event.start = newStart; + if (newEnd) { + event.end = newEnd; + } + this.events = [...this.events]; + } + + onSelectTaskgroup(taskgroup: TaskOverviewData) { + this.tasks = []; + taskgroup.tasks.forEach(task => { + this.tasks.push({ + title: task.taskName, + color: colors['yellow'], + start: new Date(), + draggable: true, + cssClass: 'test', + resizable: { + beforeStart: true, + afterEnd: true + }, + meta: { + taskID: task.taskID, + scheduleID: undefined, + taskgroupID: taskgroup.taskgroupID + }, + //actions: this.actions + }) + }) + this.taskgroupID = taskgroup.taskgroupID; + } + + private computeTaskPath(taskgroupPath: Array, task: TaskShortInfo) { + let result = ""; + taskgroupPath.forEach(taskgroupPathPart => { + result += taskgroupPathPart.taskgroupName + "/" + }); + result += task!.taskName + return result; + } + + eventClicked(click: string, event: CalendarEvent) { + + } + + register() { + this.scheduleService.schedulesTaskIDForgottenPost(this.events[0].meta.taskID, { + startTime: moment(this.events[0].start).format('YYYY-MM-DDTHH:mm:ss.SSSZ'), + endTime: moment(this.events[0].end).format('YYYY-MM-DDTHH:mm:ss.SSSZ'), + }).subscribe({ next: resp => { - this.tasks = resp; - this.filteredOptions = this.myControl.valueChanges.pipe( - startWith(''), - map(value => this._filter(value || '')), - ); - }, - error: err => { - this.snackbar.open("Unexpected error", "", {duration: 2000}); + this.router.navigateByUrl("/"); } }) } - - private _filter(value: string): string[] { - const filterValue = value.toLowerCase(); - - return this.tasks.map(x => x.taskName).filter(option => option.toLowerCase().includes(filterValue)) - } - - registerActivity() { - const task = this.tasks.find(task => task.taskName === this.myControl.value); - if(task != undefined) { - /*this.scheduleService.schedulesTaskIDForgottenPost(task.taskID, { - mode: this.determineRegisterMode(), - minutesSpent: this.minutesSpentControl.value - }).subscribe({ - next: resp => { - this.dialogRef.close(resp); - }, - error: err => { - if(err.status == 400) { - this.snackbar.open("Invalid Operation", "", {duration: 2000}); - } else 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}); - } - } - })*/ - } - } } -- 2.34.1 From edcd0f6c77ee0439464c7708fed17f2db7ffb272 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20B=C3=B6ckelmann?= Date: Sat, 18 Nov 2023 18:38:11 +0100 Subject: [PATCH 2/3] Display existing schedules in forgetten schedules scheduler --- .../scheduleInfos/ScheduleInfo.java | 4 ++-- .../java/core/entities/timemanager/Task.java | 1 + .../forgotten-task-start-dialog.component.ts | 20 +++++++++++++++++++ 3 files changed, 23 insertions(+), 2 deletions(-) diff --git a/backend/src/main/java/core/api/models/timemanager/taskSchedule/scheduleInfos/ScheduleInfo.java b/backend/src/main/java/core/api/models/timemanager/taskSchedule/scheduleInfos/ScheduleInfo.java index 1d2fe62..792b19d 100644 --- a/backend/src/main/java/core/api/models/timemanager/taskSchedule/scheduleInfos/ScheduleInfo.java +++ b/backend/src/main/java/core/api/models/timemanager/taskSchedule/scheduleInfos/ScheduleInfo.java @@ -17,7 +17,7 @@ public abstract class ScheduleInfo { @JsonProperty private LocalDateTime startTime; @JsonProperty - private LocalDateTime stopTime; + private LocalDateTime finishedTime; @JsonProperty private int activeMinutes; @JsonProperty @@ -29,7 +29,7 @@ public abstract class ScheduleInfo { this.scheduleID = scheduleID; this.scheduleType = scheduleType; this.startTime = startTime; - this.stopTime = stopTime; + this.finishedTime = stopTime; this.activeMinutes = activeMinutes; this.task = new TaskShortInfo(task); this.taskgroupPath = taskgroupPath; diff --git a/backend/src/main/java/core/entities/timemanager/Task.java b/backend/src/main/java/core/entities/timemanager/Task.java index e2fb81e..5209379 100644 --- a/backend/src/main/java/core/entities/timemanager/Task.java +++ b/backend/src/main/java/core/entities/timemanager/Task.java @@ -39,6 +39,7 @@ public class Task { private int workTime; public Task() { + this.basicTaskSchedules = new ArrayList<>(); } public Task(Taskgroup taskgroup, TaskFieldInfo taskFieldInfo) { 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 dadc140..ba407bc 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 @@ -61,7 +61,27 @@ export class ForgottenTaskStartDialogComponent implements OnInit{ } ngOnInit() { + this.scheduleService.schedulesDateStartableGet(moment().format("yyyy-MM-DD"), false).subscribe({ + next: resp => { + resp.forEach(schedule => { + console.log(schedule.startTime) + console.log(schedule.finishedTime) + this.events.push({ + title: this.computeTaskPath(schedule.taskgroupPath, schedule.task), + color: colors['red'], + start: new Date(schedule.startTime), + end: new Date(schedule.finishedTime!), + draggable: false, + resizable: { + beforeStart: false, + afterEnd: false + } + }) + }) + this.refresh.next() + } + }) } -- 2.34.1 From 5f60470e2a4ce5f092ccb4ec61a647ba8c3210ae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20B=C3=B6ckelmann?= Date: Sat, 18 Nov 2023 18:45:38 +0100 Subject: [PATCH 3/3] Reset select task in forgotten task scheduler --- .../forgotten-task-start-dialog.component.ts | 29 +++++++++++++++---- 1 file changed, 23 insertions(+), 6 deletions(-) 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 ba407bc..ea68ba4 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 @@ -12,7 +12,7 @@ import {DialogRef} from "@angular/cdk/dialog"; import {MatDialogRef} from "@angular/material/dialog"; import {filter, map, Observable, startWith, Subject} from "rxjs"; import {FormControl} from "@angular/forms"; -import {CalendarEvent, CalendarEventTimesChangedEvent} from "angular-calendar"; +import {CalendarEvent, CalendarEventAction, CalendarEventTimesChangedEvent} from "angular-calendar"; import * as moment from "moment/moment"; import {EventColor} from "calendar-utils"; import {TaskOverviewData} from "../taskgroup-overview/taskgroup-overview.component"; @@ -55,6 +55,17 @@ export class ForgottenTaskStartDialogComponent implements OnInit{ taskgroupSelected: boolean = false; + actions: CalendarEventAction[] = [ + { + label: '', + a11yLabel: 'Delete', + onClick: ({ event }: { event: CalendarEvent }): void => { + this.events = this.events.filter((iEvent) => iEvent !== event); + this.eventClicked('Deleted', event); + }, + }, + ]; + constructor(private router: Router, private scheduleService: ScheduleService) { @@ -64,8 +75,6 @@ export class ForgottenTaskStartDialogComponent implements OnInit{ this.scheduleService.schedulesDateStartableGet(moment().format("yyyy-MM-DD"), false).subscribe({ next: resp => { resp.forEach(schedule => { - console.log(schedule.startTime) - console.log(schedule.finishedTime) this.events.push({ title: this.computeTaskPath(schedule.taskgroupPath, schedule.task), color: colors['red'], @@ -75,7 +84,12 @@ export class ForgottenTaskStartDialogComponent implements OnInit{ resizable: { beforeStart: false, afterEnd: false - } + }, + meta: { + taskID: schedule.task.taskID, + scheduleID: schedule.scheduleID, + taskgroupID: schedule.taskgroupPath[schedule.taskgroupPath.length-1].taskgroupID + }, }) }) this.refresh.next() @@ -132,7 +146,7 @@ export class ForgottenTaskStartDialogComponent implements OnInit{ scheduleID: undefined, taskgroupID: taskgroup.taskgroupID }, - //actions: this.actions + actions: this.actions }) }) this.taskgroupID = taskgroup.taskgroupID; @@ -148,7 +162,10 @@ export class ForgottenTaskStartDialogComponent implements OnInit{ } eventClicked(click: string, event: CalendarEvent) { - + if(click == 'Deleted') { + this.events = this.events.filter(se => se !== event); + this.taskgroupSelected = false; + } } register() { -- 2.34.1