Stop and Finish TaskSchedules

This commit is contained in:
Sebastian 2023-10-26 09:40:36 +02:00
parent 606e89b287
commit 004d376daf
16 changed files with 307 additions and 37 deletions

View File

@ -5,12 +5,22 @@
</component> </component>
<component name="ChangeListManager"> <component name="ChangeListManager">
<list default="true" id="3a869f59-290a-4ab2-b036-a878ce801bc4" name="Changes" comment="Fix Foreign Key Constraint Fail when deleting Taskgroups"> <list default="true" id="3a869f59-290a-4ab2-b036-a878ce801bc4" name="Changes" comment="Fix Foreign Key Constraint Fail when deleting Taskgroups">
<change afterPath="$PROJECT_DIR$/src/main/java/core/api/models/timemanager/taskSchedule/ScheduleActivateInfo.java" afterDir="false" /> <change afterPath="$PROJECT_DIR$/src/main/java/core/api/models/timemanager/taskSchedule/TaskScheduleStopResponse.java" afterDir="false" />
<change afterPath="$PROJECT_DIR$/../frontend/src/app/dashboard/active-schedule/StopActiveScheduleInfo.ts" afterDir="false" />
<change beforePath="$PROJECT_DIR$/.idea/workspace.xml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/workspace.xml" afterDir="false" /> <change beforePath="$PROJECT_DIR$/.idea/workspace.xml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/workspace.xml" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/main/java/core/api/controller/ScheduleController.java" beforeDir="false" afterPath="$PROJECT_DIR$/src/main/java/core/api/controller/ScheduleController.java" afterDir="false" /> <change beforePath="$PROJECT_DIR$/src/main/java/core/api/controller/ScheduleController.java" beforeDir="false" afterPath="$PROJECT_DIR$/src/main/java/core/api/controller/ScheduleController.java" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/main/java/core/api/models/timemanager/taskSchedule/ScheduleInfo.java" beforeDir="false" afterPath="$PROJECT_DIR$/src/main/java/core/api/models/timemanager/taskSchedule/ScheduleInfo.java" afterDir="false" /> <change beforePath="$PROJECT_DIR$/src/main/java/core/api/models/timemanager/taskSchedule/ScheduleInfo.java" beforeDir="false" afterPath="$PROJECT_DIR$/src/main/java/core/api/models/timemanager/taskSchedule/ScheduleInfo.java" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/main/java/core/repositories/timemanager/BasicTaskScheduleRepository.java" beforeDir="false" afterPath="$PROJECT_DIR$/src/main/java/core/repositories/timemanager/BasicTaskScheduleRepository.java" afterDir="false" /> <change beforePath="$PROJECT_DIR$/src/main/java/core/entities/timemanager/BasicTaskSchedule.java" beforeDir="false" afterPath="$PROJECT_DIR$/src/main/java/core/entities/timemanager/BasicTaskSchedule.java" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/main/java/core/services/ServiceExitCode.java" beforeDir="false" afterPath="$PROJECT_DIR$/src/main/java/core/services/ServiceExitCode.java" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/main/java/core/services/TaskScheduleService.java" beforeDir="false" afterPath="$PROJECT_DIR$/src/main/java/core/services/TaskScheduleService.java" afterDir="false" /> <change beforePath="$PROJECT_DIR$/src/main/java/core/services/TaskScheduleService.java" beforeDir="false" afterPath="$PROJECT_DIR$/src/main/java/core/services/TaskScheduleService.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/schedule.service.ts" beforeDir="false" afterPath="$PROJECT_DIR$/../frontend/src/api/api/schedule.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/dashboard/active-schedule/active-schedule.component.html" beforeDir="false" afterPath="$PROJECT_DIR$/../frontend/src/app/dashboard/active-schedule/active-schedule.component.html" afterDir="false" />
<change beforePath="$PROJECT_DIR$/../frontend/src/app/dashboard/active-schedule/active-schedule.component.ts" beforeDir="false" afterPath="$PROJECT_DIR$/../frontend/src/app/dashboard/active-schedule/active-schedule.component.ts" afterDir="false" />
<change beforePath="$PROJECT_DIR$/../frontend/src/app/dashboard/dashboard.component.html" beforeDir="false" afterPath="$PROJECT_DIR$/../frontend/src/app/dashboard/dashboard.component.html" afterDir="false" />
<change beforePath="$PROJECT_DIR$/../frontend/src/app/dashboard/dashboard.component.ts" beforeDir="false" afterPath="$PROJECT_DIR$/../frontend/src/app/dashboard/dashboard.component.ts" afterDir="false" />
<change beforePath="$PROJECT_DIR$/../openapi.yaml" beforeDir="false" afterPath="$PROJECT_DIR$/../openapi.yaml" afterDir="false" />
</list> </list>
<option name="SHOW_DIALOG" value="false" /> <option name="SHOW_DIALOG" value="false" />
<option name="HIGHLIGHT_CONFLICTS" value="true" /> <option name="HIGHLIGHT_CONFLICTS" value="true" />
@ -101,7 +111,8 @@
<workItem from="1698067098771" duration="4770000" /> <workItem from="1698067098771" duration="4770000" />
<workItem from="1698127431684" duration="2039000" /> <workItem from="1698127431684" duration="2039000" />
<workItem from="1698164397550" duration="2329000" /> <workItem from="1698164397550" duration="2329000" />
<workItem from="1698246651541" duration="4710000" /> <workItem from="1698246651541" duration="5106000" />
<workItem from="1698298897364" duration="2350000" />
</task> </task>
<task id="LOCAL-00001" summary="Structure Taskgroups in Hierarchies"> <task id="LOCAL-00001" summary="Structure Taskgroups in Hierarchies">
<option name="closed" value="true" /> <option name="closed" value="true" />
@ -205,8 +216,18 @@
</line-breakpoint> </line-breakpoint>
<line-breakpoint enabled="true" type="java-line"> <line-breakpoint enabled="true" type="java-line">
<url>file://$PROJECT_DIR$/src/main/java/core/api/controller/ScheduleController.java</url> <url>file://$PROJECT_DIR$/src/main/java/core/api/controller/ScheduleController.java</url>
<line>42</line> <line>158</line>
<option name="timeStamp" value="2" /> <option name="timeStamp" value="3" />
</line-breakpoint>
<line-breakpoint enabled="true" type="java-line">
<url>file://$PROJECT_DIR$/src/main/java/core/api/controller/ScheduleController.java</url>
<line>167</line>
<option name="timeStamp" value="4" />
</line-breakpoint>
<line-breakpoint enabled="true" type="java-line">
<url>file://$PROJECT_DIR$/src/main/java/core/services/TaskScheduleService.java</url>
<line>123</line>
<option name="timeStamp" value="5" />
</line-breakpoint> </line-breakpoint>
</breakpoints> </breakpoints>
</breakpoint-manager> </breakpoint-manager>

View File

@ -1,10 +1,7 @@
package core.api.controller; package core.api.controller;
import core.api.models.auth.SimpleStatusResponse; import core.api.models.auth.SimpleStatusResponse;
import core.api.models.timemanager.taskSchedule.BasicTaskScheduleEntityInfo; import core.api.models.timemanager.taskSchedule.*;
import core.api.models.timemanager.taskSchedule.BasicTaskScheduleFieldInfo;
import core.api.models.timemanager.taskSchedule.ScheduleActivateInfo;
import core.api.models.timemanager.taskSchedule.ScheduleInfo;
import core.entities.timemanager.BasicTaskSchedule; import core.entities.timemanager.BasicTaskSchedule;
import core.entities.timemanager.ScheduleType; import core.entities.timemanager.ScheduleType;
import core.entities.timemanager.Task; import core.entities.timemanager.Task;
@ -103,9 +100,9 @@ public class ScheduleController {
return ResponseEntity.ok(new SimpleStatusResponse("success")); return ResponseEntity.ok(new SimpleStatusResponse("success"));
} }
@GetMapping("/schedules/today") @GetMapping("/schedules/today/{activateable}")
public ResponseEntity<?> loadTodaysSchedules() { public ResponseEntity<?> loadTodaysSchedules(@PathVariable boolean activateable) {
ServiceResult<List<BasicTaskSchedule>> todaysSchedules = taskScheduleService.loadTodaysSchedule(SecurityContextHolder.getContext().getAuthentication().getName()); ServiceResult<List<BasicTaskSchedule>> todaysSchedules = taskScheduleService.loadTodaysSchedule(SecurityContextHolder.getContext().getAuthentication().getName(), activateable);
if(todaysSchedules.getExitCode() == ServiceExitCode.MISSING_ENTITY) { if(todaysSchedules.getExitCode() == ServiceExitCode.MISSING_ENTITY) {
return ResponseEntity.status(403).body(new SimpleStatusResponse("failed")); return ResponseEntity.status(403).body(new SimpleStatusResponse("failed"));
} else { } else {
@ -145,7 +142,7 @@ public class ScheduleController {
public ResponseEntity<?> getActiveSchedule() { public ResponseEntity<?> getActiveSchedule() {
ServiceResult<BasicTaskSchedule> activeScheduleResult = taskScheduleService.getActiveSchedule(SecurityContextHolder.getContext().getAuthentication().getName()); ServiceResult<BasicTaskSchedule> activeScheduleResult = taskScheduleService.getActiveSchedule(SecurityContextHolder.getContext().getAuthentication().getName());
if(activeScheduleResult.getExitCode() == ServiceExitCode.MISSING_ENTITY) { if(activeScheduleResult.getExitCode() == ServiceExitCode.MISSING_ENTITY) {
return ResponseEntity.status(404).body(new SimpleStatusResponse("failed")); return ResponseEntity.ok(new ScheduleInfo());
} else { } else {
return ResponseEntity.ok(new ScheduleInfo(activeScheduleResult.getResult())); return ResponseEntity.ok(new ScheduleInfo(activeScheduleResult.getResult()));
} }
@ -165,8 +162,31 @@ public class ScheduleController {
ServiceResult<BasicTaskSchedule> scheduleActivateResult = taskScheduleService.activateSchedule(schedulePermissionResult.getResult()); ServiceResult<BasicTaskSchedule> scheduleActivateResult = taskScheduleService.activateSchedule(schedulePermissionResult.getResult());
if(scheduleActivateResult.getExitCode() == ServiceExitCode.ENTITY_ALREADY_EXIST) { if(scheduleActivateResult.getExitCode() == ServiceExitCode.ENTITY_ALREADY_EXIST) {
return ResponseEntity.status(409).body(new SimpleStatusResponse("failed")); return ResponseEntity.status(409).body(new SimpleStatusResponse("failed"));
} else { } else if(scheduleActivateResult.getExitCode() == ServiceExitCode.OK){
return ResponseEntity.ok(new ScheduleActivateInfo(scheduleActivateResult.getResult().getStartTime())); return ResponseEntity.ok(new ScheduleActivateInfo(scheduleActivateResult.getResult().getStartTime()));
} else {
return ResponseEntity.status(404).body(new SimpleStatusResponse("failed"));
} }
} }
@PostMapping("/schedules/{scheduleID}/stop/{finish}")
public ResponseEntity<?> stopSchedule(@PathVariable long scheduleID, @PathVariable boolean finish) {
PermissionResult<BasicTaskSchedule> schedulePermissionResult = taskScheduleService.getSchedulePermissions(scheduleID, SecurityContextHolder.getContext().getAuthentication().getName());
if(!schedulePermissionResult.isHasPermissions()) {
return ResponseEntity.status(403).body(new SimpleStatusResponse("failed"));
}
if(schedulePermissionResult.getExitCode() == ServiceExitCode.MISSING_ENTITY) {
return ResponseEntity.status(404).body(new SimpleStatusResponse("failed"));
}
ServiceResult<Integer> stopResult = taskScheduleService.stopSchedule(schedulePermissionResult.getResult());
if(stopResult.getExitCode() == ServiceExitCode.INVALID_OPERATION) {
return ResponseEntity.status(400).body(new SimpleStatusResponse("failed"));
} else {
return ResponseEntity.ok(new TaskScheduleStopResponse(stopResult.getResult()));
}
}
} }

View File

@ -44,6 +44,10 @@ public class ScheduleInfo {
this.taskgroupPath = taskgroupPath.stream().map(TaskgroupEntityInfo::new).toList(); this.taskgroupPath = taskgroupPath.stream().map(TaskgroupEntityInfo::new).toList();
} }
public ScheduleInfo() {
this.scheduleID = -1;
}
public long getScheduleID() { public long getScheduleID() {
return scheduleID; return scheduleID;
} }

View File

@ -0,0 +1,18 @@
package core.api.models.timemanager.taskSchedule;
public class TaskScheduleStopResponse {
private int workTime;
public TaskScheduleStopResponse(int workTime) {
this.workTime = workTime;
}
public int getWorkTime() {
return workTime;
}
public void setWorkTime(int workTime) {
this.workTime = workTime;
}
}

View File

@ -75,4 +75,8 @@ public class BasicTaskSchedule {
public void setFinishedTime(LocalDateTime finishedTime) { public void setFinishedTime(LocalDateTime finishedTime) {
this.finishedTime = finishedTime; this.finishedTime = finishedTime;
} }
public boolean isActivateAble() {
return startTime == null;
}
} }

View File

@ -4,5 +4,6 @@ public enum ServiceExitCode {
OK, OK,
ENTITY_ALREADY_EXIST, ENTITY_ALREADY_EXIST,
MISSING_ENTITY; MISSING_ENTITY,
INVALID_OPERATION;
} }

View File

@ -10,6 +10,7 @@ import core.repositories.timemanager.TaskRepository;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import java.time.Duration;
import java.time.LocalDate; import java.time.LocalDate;
import java.time.LocalDateTime; import java.time.LocalDateTime;
import java.util.List; import java.util.List;
@ -53,10 +54,21 @@ public class TaskScheduleService {
basicTaskScheduleRepository.deleteBasicTaskScheduleByID(basicTaskSchedule.getScheduleID()); basicTaskScheduleRepository.deleteBasicTaskScheduleByID(basicTaskSchedule.getScheduleID());
} }
public ServiceResult<List<BasicTaskSchedule>> loadTodaysSchedule(String username) { public ServiceResult<List<BasicTaskSchedule>> loadTodaysSchedule(String username, boolean onlyActivateable) {
Optional<User> user = userRepository.findByUsername(username); Optional<User> user = userRepository.findByUsername(username);
return user.map(value -> new ServiceResult<>(basicTaskScheduleRepository.findAllByUserAndDate(value, LocalDate.now()))).orElseGet(() -> if(user.isEmpty()) {
new ServiceResult<>(ServiceExitCode.MISSING_ENTITY)); return new ServiceResult<>(ServiceExitCode.MISSING_ENTITY);
}
List<BasicTaskSchedule> basicTaskSchedules = basicTaskScheduleRepository.findAllByUserAndDate(user.get(), LocalDate.now());
if(onlyActivateable) {
for(int i=0; i<basicTaskSchedules.size(); i++) {
if(!basicTaskSchedules.get(i).isActivateAble()) {
basicTaskSchedules.remove(i);
}
}
}
return new ServiceResult<>(basicTaskSchedules);
} }
public ServiceResult<List<BasicTaskSchedule>> loadSchedules(String username) { public ServiceResult<List<BasicTaskSchedule>> loadSchedules(String username) {
@ -88,6 +100,11 @@ public class TaskScheduleService {
} }
public ServiceResult<BasicTaskSchedule> activateSchedule(BasicTaskSchedule taskSchedule) { public ServiceResult<BasicTaskSchedule> activateSchedule(BasicTaskSchedule taskSchedule) {
//Check if taskSchedule can be started
if(taskSchedule.getStartTime() != null) {
return new ServiceResult<>(ServiceExitCode.INVALID_OPERATION);
}
if(getActiveSchedule(taskSchedule.getTask().getTaskgroup().getUser().getUsername()).getExitCode() == ServiceExitCode.MISSING_ENTITY) { if(getActiveSchedule(taskSchedule.getTask().getTaskgroup().getUser().getUsername()).getExitCode() == ServiceExitCode.MISSING_ENTITY) {
taskSchedule.setStartTime(LocalDateTime.now()); taskSchedule.setStartTime(LocalDateTime.now());
basicTaskScheduleRepository.save(taskSchedule); basicTaskScheduleRepository.save(taskSchedule);
@ -96,4 +113,19 @@ public class TaskScheduleService {
return new ServiceResult<>(ServiceExitCode.ENTITY_ALREADY_EXIST); return new ServiceResult<>(ServiceExitCode.ENTITY_ALREADY_EXIST);
} }
} }
public ServiceResult<Integer> stopSchedule(BasicTaskSchedule taskSchedule) {
if(taskSchedule.getStartTime() == null || taskSchedule.getFinishedTime() != null) {
return new ServiceResult<>(ServiceExitCode.INVALID_OPERATION);
}
taskSchedule.setFinishedTime(LocalDateTime.now());
long activeTime = Duration.between(taskSchedule.getStartTime(), taskSchedule.getFinishedTime()).toMinutes();
long workTime = (taskSchedule.getTask().getWorkTime() + activeTime);
int workTime_i = (int) (workTime);
taskSchedule.getTask().setWorkTime(workTime_i);
basicTaskScheduleRepository.save(taskSchedule);
taskRepository.save(taskSchedule.getTask());
return new ServiceResult<>(workTime_i);
}
} }

View File

@ -34,6 +34,7 @@ model/signUpRequest.ts
model/simpleStatusResponse.ts model/simpleStatusResponse.ts
model/taskEntityInfo.ts model/taskEntityInfo.ts
model/taskFieldInfo.ts model/taskFieldInfo.ts
model/taskScheduleStopResponse.ts
model/taskShortInfo.ts model/taskShortInfo.ts
model/taskgroupDetailInfo.ts model/taskgroupDetailInfo.ts
model/taskgroupEntityInfo.ts model/taskgroupEntityInfo.ts

View File

@ -23,6 +23,7 @@ import { BasicScheduleFieldInfo } from '../model/models';
import { ScheduleActivateInfo } from '../model/models'; import { ScheduleActivateInfo } from '../model/models';
import { ScheduleInfo } from '../model/models'; import { ScheduleInfo } from '../model/models';
import { SimpleStatusResponse } from '../model/models'; import { SimpleStatusResponse } from '../model/models';
import { TaskScheduleStopResponse } from '../model/models';
import { BASE_PATH, COLLECTION_FORMATS } from '../variables'; import { BASE_PATH, COLLECTION_FORMATS } from '../variables';
import { Configuration } from '../configuration'; import { Configuration } from '../configuration';
@ -392,6 +393,68 @@ export class ScheduleService {
); );
} }
/**
* @param scheduleID internal id of schedule
* @param finish internal id of schedule
* @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 schedulesScheduleIDStopFinishPost(scheduleID: number, finish: boolean, observe?: 'body', reportProgress?: boolean, options?: {httpHeaderAccept?: 'application/json', context?: HttpContext}): Observable<TaskScheduleStopResponse>;
public schedulesScheduleIDStopFinishPost(scheduleID: number, finish: boolean, observe?: 'response', reportProgress?: boolean, options?: {httpHeaderAccept?: 'application/json', context?: HttpContext}): Observable<HttpResponse<TaskScheduleStopResponse>>;
public schedulesScheduleIDStopFinishPost(scheduleID: number, finish: boolean, observe?: 'events', reportProgress?: boolean, options?: {httpHeaderAccept?: 'application/json', context?: HttpContext}): Observable<HttpEvent<TaskScheduleStopResponse>>;
public schedulesScheduleIDStopFinishPost(scheduleID: number, finish: boolean, observe: any = 'body', reportProgress: boolean = false, options?: {httpHeaderAccept?: 'application/json', context?: HttpContext}): Observable<any> {
if (scheduleID === null || scheduleID === undefined) {
throw new Error('Required parameter scheduleID was null or undefined when calling schedulesScheduleIDStopFinishPost.');
}
if (finish === null || finish === undefined) {
throw new Error('Required parameter finish was null or undefined when calling schedulesScheduleIDStopFinishPost.');
}
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.post<TaskScheduleStopResponse>(`${this.configuration.basePath}/schedules/${encodeURIComponent(String(scheduleID))}/stop/${encodeURIComponent(String(finish))}`,
null,
{
context: localVarHttpContext,
responseType: <any>responseType_,
withCredentials: this.configuration.withCredentials,
headers: localVarHeaders,
observe: observe,
reportProgress: reportProgress
}
);
}
/** /**
* creates basic schedule for task * creates basic schedule for task
* creates a basic schedule for a task * creates a basic schedule for a task
@ -588,13 +651,17 @@ export class ScheduleService {
/** /**
* get today\&#39;s schedules * get today\&#39;s schedules
* get all schedules of today * get all schedules of today
* @param activateable determines whether only schedules that can be started should be included or all schedules of today
* @param observe set whether or not to return the data Observable as the body, response or events. defaults to returning the body. * @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. * @param reportProgress flag to report request and response progress.
*/ */
public schedulesTodayGet(observe?: 'body', reportProgress?: boolean, options?: {httpHeaderAccept?: 'application/json', context?: HttpContext}): Observable<Array<ScheduleInfo>>; public schedulesTodayActivateableGet(activateable: boolean, observe?: 'body', reportProgress?: boolean, options?: {httpHeaderAccept?: 'application/json', context?: HttpContext}): Observable<Array<ScheduleInfo>>;
public schedulesTodayGet(observe?: 'response', reportProgress?: boolean, options?: {httpHeaderAccept?: 'application/json', context?: HttpContext}): Observable<HttpResponse<Array<ScheduleInfo>>>; public schedulesTodayActivateableGet(activateable: boolean, observe?: 'response', reportProgress?: boolean, options?: {httpHeaderAccept?: 'application/json', context?: HttpContext}): Observable<HttpResponse<Array<ScheduleInfo>>>;
public schedulesTodayGet(observe?: 'events', reportProgress?: boolean, options?: {httpHeaderAccept?: 'application/json', context?: HttpContext}): Observable<HttpEvent<Array<ScheduleInfo>>>; public schedulesTodayActivateableGet(activateable: boolean, observe?: 'events', reportProgress?: boolean, options?: {httpHeaderAccept?: 'application/json', context?: HttpContext}): Observable<HttpEvent<Array<ScheduleInfo>>>;
public schedulesTodayGet(observe: any = 'body', reportProgress: boolean = false, options?: {httpHeaderAccept?: 'application/json', context?: HttpContext}): Observable<any> { public schedulesTodayActivateableGet(activateable: boolean, observe: any = 'body', reportProgress: boolean = false, options?: {httpHeaderAccept?: 'application/json', context?: HttpContext}): Observable<any> {
if (activateable === null || activateable === undefined) {
throw new Error('Required parameter activateable was null or undefined when calling schedulesTodayActivateableGet.');
}
let localVarHeaders = this.defaultHeaders; let localVarHeaders = this.defaultHeaders;
@ -628,7 +695,7 @@ export class ScheduleService {
responseType_ = 'text'; responseType_ = 'text';
} }
return this.httpClient.get<Array<ScheduleInfo>>(`${this.configuration.basePath}/schedules/today`, return this.httpClient.get<Array<ScheduleInfo>>(`${this.configuration.basePath}/schedules/today/${encodeURIComponent(String(activateable))}`,
{ {
context: localVarHttpContext, context: localVarHttpContext,
responseType: <any>responseType_, responseType: <any>responseType_,

View File

@ -18,6 +18,7 @@ export * from './signUpRequest';
export * from './simpleStatusResponse'; export * from './simpleStatusResponse';
export * from './taskEntityInfo'; export * from './taskEntityInfo';
export * from './taskFieldInfo'; export * from './taskFieldInfo';
export * from './taskScheduleStopResponse';
export * from './taskShortInfo'; export * from './taskShortInfo';
export * from './taskgroupDetailInfo'; export * from './taskgroupDetailInfo';
export * from './taskgroupEntityInfo'; export * from './taskgroupEntityInfo';

View File

@ -0,0 +1,6 @@
import {ScheduleInfo} from "../../../api";
export interface StopActiveScheduleInfo {
schedule: ScheduleInfo
workedMinutes: number
}

View File

@ -13,7 +13,7 @@
<p class="gray-text" *ngIf="activeSchedule!.scheduleType==='BASIC'">Running for {{displayTime}}</p> <p class="gray-text" *ngIf="activeSchedule!.scheduleType==='BASIC'">Running for {{displayTime}}</p>
</mat-card-content> </mat-card-content>
<mat-card-actions> <mat-card-actions>
<button mat-raised-button class="grayBtn">Stop</button> <button mat-raised-button class="grayBtn" (click)="stopTask(false)">Stop</button>
<button mat-raised-button class="greenBtn">Finish</button> <button mat-raised-button class="greenBtn" (click)="stopTask(true)">Finish</button>
</mat-card-actions> </mat-card-actions>
</mat-card> </mat-card>

View File

@ -1,5 +1,6 @@
import {Component, Input, OnInit} from '@angular/core'; import {Component, EventEmitter, Input, OnInit, Output} from '@angular/core';
import {ScheduleInfo, ScheduleService} from "../../../api"; import {ScheduleInfo, ScheduleService} from "../../../api";
import {StopActiveScheduleInfo} from "./StopActiveScheduleInfo";
@Component({ @Component({
selector: 'app-active-schedule', selector: 'app-active-schedule',
@ -13,6 +14,8 @@ export class ActiveScheduleComponent implements OnInit{
currentTime: number = 0; currentTime: number = 0;
displayTime: string = "00:00:00" displayTime: string = "00:00:00"
@Output('onStopTask') scheduleStopEmitter = new EventEmitter<StopActiveScheduleInfo>;
constructor(private scheduleService: ScheduleService) { constructor(private scheduleService: ScheduleService) {
@ -40,12 +43,32 @@ export class ActiveScheduleComponent implements OnInit{
ngOnInit(): void { ngOnInit(): void {
this.scheduleService.schedulesActiveGet().subscribe({ this.scheduleService.schedulesActiveGet().subscribe({
next: resp => { next: resp => {
this.activeSchedule = resp; if(resp.scheduleID >= 0) {
this.startTime = new Date(this.activeSchedule.startTime).getTime(); this.activateSchedule(resp);
this.updateTime() }
},
})
}
stopTask(finish: boolean) {
this.scheduleService.schedulesScheduleIDStopFinishPost(this.activeSchedule!.scheduleID, finish).subscribe({
next: resp => {
this.scheduleStopEmitter.emit({
schedule: this.activeSchedule!,
workedMinutes: resp.workTime
})
this.activeSchedule = undefined
} }
}) })
} }
activateSchedule(schedule: ScheduleInfo) {
this.activeSchedule = schedule;
this.startTime = new Date(this.activeSchedule.startTime).getTime();
this.updateTime();
}
} }

View File

@ -6,9 +6,9 @@
<a class="btn-link" routerLink="/">Reschedule</a> <a class="btn-link" routerLink="/">Reschedule</a>
</mat-card-content> </mat-card-content>
</mat-card> </mat-card>
<h1 class="dashboard-heading">Now<b class="today-worked-info">Today: 0 min</b></h1> <h1 class="dashboard-heading">Now<b class="today-worked-info">Today: {{workedMinutesToday}} min</b></h1>
<app-active-schedule #activeSchedule></app-active-schedule> <app-active-schedule #activeSchedule (onStopTask)="stopedTask($event)"></app-active-schedule>
<h1 class="dashboard-heading">Scheduled for today</h1> <h1 class="dashboard-heading">Scheduled for today</h1>
<mat-card class="green-card" *ngIf="schedules.length == 0"> <mat-card class="green-card" *ngIf="schedules.length == 0">

View File

@ -1,6 +1,7 @@
import {Component, OnInit, ViewChild} from '@angular/core'; import {Component, OnInit, ViewChild} from '@angular/core';
import {ScheduleInfo, ScheduleService} from "../../api"; import {ScheduleInfo, ScheduleService} from "../../api";
import {ActiveScheduleComponent} from "./active-schedule/active-schedule.component"; import {ActiveScheduleComponent} from "./active-schedule/active-schedule.component";
import {StopActiveScheduleInfo} from "./active-schedule/StopActiveScheduleInfo";
@Component({ @Component({
selector: 'app-dashboard', selector: 'app-dashboard',
@ -11,19 +12,18 @@ export class DashboardComponent implements OnInit{
missedSchedules: boolean = true missedSchedules: boolean = true
schedules: ScheduleInfo[] = [] schedules: ScheduleInfo[] = []
workedMinutesToday: number = 0
@ViewChild('activeSchedule') activeScheduleComponent: ActiveScheduleComponent | undefined @ViewChild('activeSchedule') activeScheduleComponent: ActiveScheduleComponent | undefined
constructor(private scheduleService: ScheduleService) { constructor(private scheduleService: ScheduleService) {
} }
ngOnInit() { ngOnInit() {
this.scheduleService.schedulesTodayGet().subscribe({ this.scheduleService.schedulesTodayActivateableGet(true).subscribe({
next: resp => { next: resp => {
this.schedules = resp; this.schedules = resp;
} }
}) })
} }
startSchedule(schedule: ScheduleInfo) { startSchedule(schedule: ScheduleInfo) {
@ -31,11 +31,14 @@ export class DashboardComponent implements OnInit{
next: resp => { next: resp => {
schedule.startTime = resp.startTime; schedule.startTime = resp.startTime;
if(this.activeScheduleComponent != undefined) { if(this.activeScheduleComponent != undefined) {
this.activeScheduleComponent.activeSchedule = schedule; this.activeScheduleComponent.activateSchedule(schedule);
} }
} }
}) })
} }
stopedTask(stopActiveScheduleInfo: StopActiveScheduleInfo) {
this.workedMinutesToday += stopActiveScheduleInfo.workedMinutes;
}
} }

View File

@ -1355,7 +1355,7 @@ paths:
schema: schema:
type: object type: object
$ref: "#/components/schemas/SimpleStatusResponse" $ref: "#/components/schemas/SimpleStatusResponse"
/schedules/today: /schedules/today/{activateable}:
get: get:
security: security:
- API_TOKEN: [] - API_TOKEN: []
@ -1363,6 +1363,15 @@ paths:
- schedule - schedule
description: get all schedules of today description: get all schedules of today
summary: get today's schedules summary: get today's schedules
parameters:
- name: activateable
in: path
description: determines whether only schedules that can be started should be included or all schedules of today
required: true
schema:
type: boolean
example: true
responses: responses:
200: 200:
description: Operation successfull description: Operation successfull
@ -1483,6 +1492,57 @@ paths:
schema: schema:
type: object type: object
$ref: "#/components/schemas/SimpleStatusResponse" $ref: "#/components/schemas/SimpleStatusResponse"
/schedules/{scheduleID}/stop/{finish}:
post:
security:
- API_TOKEN: []
tags:
- schedule
parameters:
- name: scheduleID
in: path
description: internal id of schedule
required: true
schema:
type: number
example: 1
- name: finish
in: path
description: internal id of schedule
required: true
schema:
type: boolean
example: True
responses:
200:
description: No permission
content:
'application/json':
schema:
type: object
$ref: "#/components/schemas/TaskScheduleStopResponse"
403:
description: No permission
content:
'application/json':
schema:
type: object
$ref: "#/components/schemas/SimpleStatusResponse"
404:
description: Schedule does not exist
content:
'application/json':
schema:
type: object
$ref: "#/components/schemas/SimpleStatusResponse"
400:
description: Operation not valid
content:
'application/json':
schema:
type: object
$ref: "#/components/schemas/SimpleStatusResponse"
@ -1910,3 +1970,12 @@ components:
type: string type: string
format: date-time format: date-time
description: point in time at which the schedule was started description: point in time at which the schedule was started
TaskScheduleStopResponse:
required:
- workTime
additionalProperties: false
properties:
workTime:
type: number
description: time where the schedule was active
example: 10