issue-31 #33
@ -7,6 +7,7 @@
 | 
			
		||||
    <list default="true" id="3a869f59-290a-4ab2-b036-a878ce801bc4" name="Changes" comment="Load worked minutes when reloading dashboard">
 | 
			
		||||
      <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/services/TaskScheduleService.java" beforeDir="false" afterPath="$PROJECT_DIR$/src/main/java/core/services/TaskScheduleService.java" afterDir="false" />
 | 
			
		||||
      <change beforePath="$PROJECT_DIR$/../frontend/src/app/dashboard/forgotten-task-start-dialog/forgotten-task-start-dialog.component.ts" beforeDir="false" afterPath="$PROJECT_DIR$/../frontend/src/app/dashboard/forgotten-task-start-dialog/forgotten-task-start-dialog.component.ts" afterDir="false" />
 | 
			
		||||
    </list>
 | 
			
		||||
    <option name="SHOW_DIALOG" value="false" />
 | 
			
		||||
    <option name="HIGHLIGHT_CONFLICTS" value="true" />
 | 
			
		||||
@ -16,16 +17,16 @@
 | 
			
		||||
  <component name="FileTemplateManagerImpl">
 | 
			
		||||
    <option name="RECENT_TEMPLATES">
 | 
			
		||||
      <list>
 | 
			
		||||
        <option value="Enum" />
 | 
			
		||||
        <option value="Interface" />
 | 
			
		||||
        <option value="Class" />
 | 
			
		||||
        <option value="Enum" />
 | 
			
		||||
      </list>
 | 
			
		||||
    </option>
 | 
			
		||||
  </component>
 | 
			
		||||
  <component name="Git.Settings">
 | 
			
		||||
    <option name="RECENT_BRANCH_BY_REPOSITORY">
 | 
			
		||||
      <map>
 | 
			
		||||
        <entry key="$PROJECT_DIR$/.." value="issue-23" />
 | 
			
		||||
        <entry key="$PROJECT_DIR$/.." value="issue-29" />
 | 
			
		||||
      </map>
 | 
			
		||||
    </option>
 | 
			
		||||
    <option name="RECENT_GIT_ROOT_PATH" value="$PROJECT_DIR$/.." />
 | 
			
		||||
@ -259,7 +260,8 @@
 | 
			
		||||
    <MESSAGE value="Remove update spamming in console" />
 | 
			
		||||
    <MESSAGE value="Start task now from Taskoverview in Dashboard" />
 | 
			
		||||
    <MESSAGE value="Load worked minutes when reloading dashboard" />
 | 
			
		||||
    <option name="LAST_COMMIT_MESSAGE" value="Load worked minutes when reloading dashboard" />
 | 
			
		||||
    <MESSAGE value="Check if there is another active schedule when starting task now" />
 | 
			
		||||
    <option name="LAST_COMMIT_MESSAGE" value="Check if there is another active schedule when starting task now" />
 | 
			
		||||
  </component>
 | 
			
		||||
  <component name="XDebuggerManager">
 | 
			
		||||
    <breakpoint-manager>
 | 
			
		||||
@ -271,14 +273,19 @@
 | 
			
		||||
        </line-breakpoint>
 | 
			
		||||
        <line-breakpoint enabled="true" type="java-line">
 | 
			
		||||
          <url>file://$PROJECT_DIR$/src/main/java/core/services/TaskScheduleService.java</url>
 | 
			
		||||
          <line>86</line>
 | 
			
		||||
          <line>87</line>
 | 
			
		||||
          <option name="timeStamp" value="5" />
 | 
			
		||||
        </line-breakpoint>
 | 
			
		||||
        <line-breakpoint enabled="true" type="java-line">
 | 
			
		||||
          <url>file://$PROJECT_DIR$/src/main/java/core/services/TaskScheduleService.java</url>
 | 
			
		||||
          <line>93</line>
 | 
			
		||||
          <line>94</line>
 | 
			
		||||
          <option name="timeStamp" value="6" />
 | 
			
		||||
        </line-breakpoint>
 | 
			
		||||
        <line-breakpoint enabled="true" type="java-line">
 | 
			
		||||
          <url>file://$PROJECT_DIR$/src/main/java/core/services/TaskScheduleService.java</url>
 | 
			
		||||
          <line>202</line>
 | 
			
		||||
          <option name="timeStamp" value="10" />
 | 
			
		||||
        </line-breakpoint>
 | 
			
		||||
      </breakpoints>
 | 
			
		||||
    </breakpoint-manager>
 | 
			
		||||
  </component>
 | 
			
		||||
 | 
			
		||||
@ -201,4 +201,23 @@ public class ScheduleController {
 | 
			
		||||
        int workedMinutes = taskScheduleService.getWorkedMinutes(user.get());
 | 
			
		||||
        return ResponseEntity.ok(new ScheduleStatus(workedMinutes, taskScheduleService.isAnyScheduleMissed(user.get())));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @PostMapping("/schedules/{taskID}/forgotten")
 | 
			
		||||
    public ResponseEntity<?> registerForgottenActivity(@PathVariable long taskID, @Valid @RequestBody ForgottenActivity forgottenActivity) {
 | 
			
		||||
        PermissionResult<Task> permissionResult = taskService.getTaskPermissions(taskID, SecurityContextHolder.getContext().getAuthentication().getName());
 | 
			
		||||
        if(!permissionResult.isHasPermissions()) {
 | 
			
		||||
            return ResponseEntity.status(403).body(new SimpleStatusResponse("failed"));
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if(permissionResult.getExitCode() == ServiceExitCode.MISSING_ENTITY) {
 | 
			
		||||
            return ResponseEntity.status(404).body(new SimpleStatusResponse("failed"));
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        ServiceResult<Integer> serviceResult = taskScheduleService.registerForgottenActivity(permissionResult.getResult(), forgottenActivity);
 | 
			
		||||
        if(serviceResult.getExitCode() == ServiceExitCode.INVALID_OPERATION) {
 | 
			
		||||
            return ResponseEntity.status(400).body(new SimpleStatusResponse("failed"));
 | 
			
		||||
        } else {
 | 
			
		||||
            return ResponseEntity.ok(new TaskScheduleStopResponse(serviceResult.getResult()));
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -4,6 +4,7 @@ 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.entities.timemanager.Task;
 | 
			
		||||
import core.entities.timemanager.Taskgroup;
 | 
			
		||||
import core.services.*;
 | 
			
		||||
@ -13,6 +14,9 @@ import org.springframework.security.core.context.SecurityContextHolder;
 | 
			
		||||
import org.springframework.web.bind.annotation.*;
 | 
			
		||||
 | 
			
		||||
import javax.validation.Valid;
 | 
			
		||||
import java.util.ArrayList;
 | 
			
		||||
import java.util.LinkedList;
 | 
			
		||||
import java.util.List;
 | 
			
		||||
 | 
			
		||||
@CrossOrigin(origins = "*", maxAge = 3600)
 | 
			
		||||
@RestController
 | 
			
		||||
@ -27,6 +31,24 @@ public class TaskController {
 | 
			
		||||
        this.taskgroupService = taskgroupService;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @GetMapping("/tasks/all/{finished}")
 | 
			
		||||
    public ResponseEntity<List<TaskShortInfo>> loadAllTasks(@PathVariable boolean finished) {
 | 
			
		||||
        List<Task> taskList = taskService.loadAllTasks(SecurityContextHolder.getContext().getAuthentication().getName(), finished);
 | 
			
		||||
        List<TaskShortInfo> taskShortInfos = new ArrayList<>();
 | 
			
		||||
        for(Task task : taskList) {
 | 
			
		||||
            List<Taskgroup> 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());
 | 
			
		||||
            taskShortInfos.add(new TaskShortInfo(task.getTaskID(), builder.toString()));
 | 
			
		||||
 | 
			
		||||
        }
 | 
			
		||||
        return ResponseEntity.ok(taskShortInfos);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @GetMapping("/tasks/{taskgroupID}/{status}")
 | 
			
		||||
    public ResponseEntity<?> listTasksOfTaskgroup(@PathVariable long taskgroupID, @PathVariable String status) {
 | 
			
		||||
        PermissionResult<Taskgroup> taskgroupPermissionResult = taskgroupService.getTaskgroupByIDAndUsername(taskgroupID, SecurityContextHolder.getContext().getAuthentication().getName());
 | 
			
		||||
 | 
			
		||||
@ -0,0 +1,22 @@
 | 
			
		||||
package core.api.models.timemanager.taskSchedule;
 | 
			
		||||
 | 
			
		||||
public class ForgottenActivity {
 | 
			
		||||
    private ForgottenActivityMode mode;
 | 
			
		||||
    private int minutesSpent;
 | 
			
		||||
 | 
			
		||||
    public ForgottenActivityMode getMode() {
 | 
			
		||||
        return mode;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public void setMode(ForgottenActivityMode mode) {
 | 
			
		||||
        this.mode = mode;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public int getMinutesSpent() {
 | 
			
		||||
        return minutesSpent;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public void setMinutesSpent(int minutesSpent) {
 | 
			
		||||
        this.minutesSpent = minutesSpent;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@ -0,0 +1,8 @@
 | 
			
		||||
package core.api.models.timemanager.taskSchedule;
 | 
			
		||||
 | 
			
		||||
public enum ForgottenActivityMode {
 | 
			
		||||
 | 
			
		||||
    MANUAL,
 | 
			
		||||
    LAST,
 | 
			
		||||
    PLANNED
 | 
			
		||||
}
 | 
			
		||||
@ -12,6 +12,11 @@ public class TaskShortInfo {
 | 
			
		||||
        this.taskName = task.getTaskName();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public TaskShortInfo(long taskID, String taskName) {
 | 
			
		||||
        this.taskID = taskID;
 | 
			
		||||
        this.taskName = taskName;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public long getTaskID() {
 | 
			
		||||
        return taskID;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@ -146,4 +146,8 @@ public class Task {
 | 
			
		||||
        }
 | 
			
		||||
        return false;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public void increaseActiveTime(int minutesSpent) {
 | 
			
		||||
        this.workTime += minutesSpent;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -95,6 +95,7 @@ public class Taskgroup {
 | 
			
		||||
            ancestors.add(currentTaskgroup.parent);
 | 
			
		||||
            currentTaskgroup = currentTaskgroup.parent;
 | 
			
		||||
        }
 | 
			
		||||
        //ancestors.add(taskgroup);
 | 
			
		||||
        return ancestors;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -36,4 +36,7 @@ public interface BasicTaskScheduleRepository extends CrudRepository<BasicTaskSch
 | 
			
		||||
    Optional<BasicTaskSchedule> findActiveTaskSchedule(String username);
 | 
			
		||||
 | 
			
		||||
    List<BasicTaskSchedule> findAllByStartTimeIsNull();
 | 
			
		||||
 | 
			
		||||
    @Query(value = "SELECT bts FROM BasicTaskSchedule bts WHERE bts.task.taskgroup.user = ?1 AND bts.scheduleDate = ?2 AND bts.finishedTime IS NOT NULL")
 | 
			
		||||
    List<BasicTaskSchedule> findAllFinishedByUserAndDate(User user, LocalDate now);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -8,10 +8,14 @@ import org.springframework.data.repository.CrudRepository;
 | 
			
		||||
import org.springframework.stereotype.Repository;
 | 
			
		||||
 | 
			
		||||
import javax.transaction.Transactional;
 | 
			
		||||
import java.util.List;
 | 
			
		||||
 | 
			
		||||
@Repository
 | 
			
		||||
public interface TaskRepository extends CrudRepository<Task, Long> {
 | 
			
		||||
 | 
			
		||||
    @Query(value = "SELECT t FROM Task t WHERE t.taskgroup.user.username = ?1 AND t.finished = ?2")
 | 
			
		||||
    List<Task> findAllByUser(String username, boolean finished);
 | 
			
		||||
 | 
			
		||||
    @Transactional
 | 
			
		||||
    @Modifying
 | 
			
		||||
    @Query(value = "DELETE FROM Task t WHERE t.taskgroup = ?1")
 | 
			
		||||
 | 
			
		||||
@ -1,6 +1,7 @@
 | 
			
		||||
package core.services;
 | 
			
		||||
 | 
			
		||||
import core.api.models.timemanager.taskSchedule.BasicTaskScheduleFieldInfo;
 | 
			
		||||
import core.api.models.timemanager.taskSchedule.ForgottenActivity;
 | 
			
		||||
import core.entities.User;
 | 
			
		||||
import core.entities.timemanager.BasicTaskSchedule;
 | 
			
		||||
import core.entities.timemanager.Task;
 | 
			
		||||
@ -157,4 +158,59 @@ public class TaskScheduleService {
 | 
			
		||||
        }
 | 
			
		||||
        return false;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public ServiceResult<Integer> registerForgottenActivity(Task task, ForgottenActivity forgottenActivity) {
 | 
			
		||||
        switch (forgottenActivity.getMode()) {
 | 
			
		||||
            case MANUAL -> {
 | 
			
		||||
                task.increaseActiveTime(forgottenActivity.getMinutesSpent());
 | 
			
		||||
                BasicTaskSchedule basicTaskSchedule = new BasicTaskSchedule(task, LocalDate.now());
 | 
			
		||||
                LocalDateTime timeReference = LocalDateTime.now();
 | 
			
		||||
                basicTaskSchedule.setStartTime(timeReference.minusMinutes(forgottenActivity.getMinutesSpent()));
 | 
			
		||||
                basicTaskSchedule.setFinishedTime(timeReference);
 | 
			
		||||
                task.getBasicTaskSchedules().add(basicTaskSchedule);
 | 
			
		||||
                basicTaskScheduleRepository.save(basicTaskSchedule);
 | 
			
		||||
                taskRepository.save(task);
 | 
			
		||||
                return new ServiceResult<>(forgottenActivity.getMinutesSpent());
 | 
			
		||||
            }
 | 
			
		||||
            case LAST -> {
 | 
			
		||||
                List<BasicTaskSchedule> schedules = basicTaskScheduleRepository.findAllFinishedByUserAndDate(task.getTaskgroup().getUser(), LocalDate.now());
 | 
			
		||||
                if(schedules.isEmpty()) {
 | 
			
		||||
                    return new ServiceResult<>(ServiceExitCode.INVALID_OPERATION);
 | 
			
		||||
                } else {
 | 
			
		||||
                    LocalDateTime timeReference = LocalDateTime.now();
 | 
			
		||||
                    BasicTaskSchedule nearestSchedule = null;
 | 
			
		||||
                    long nearestDuration = Long.MAX_VALUE;
 | 
			
		||||
                    for(BasicTaskSchedule schedule : schedules) {
 | 
			
		||||
                        if(nearestSchedule == null) {
 | 
			
		||||
                            nearestSchedule = schedule;
 | 
			
		||||
                            nearestDuration = Duration.between(nearestSchedule.getFinishedTime(), timeReference).getSeconds();
 | 
			
		||||
                        } else {
 | 
			
		||||
                            long currentDuration = Duration.between(schedule.getFinishedTime(), timeReference).getSeconds();
 | 
			
		||||
                            if(currentDuration < nearestDuration) {
 | 
			
		||||
                                nearestSchedule = schedule;
 | 
			
		||||
                                nearestDuration = currentDuration;
 | 
			
		||||
                            }
 | 
			
		||||
                        }
 | 
			
		||||
                    }
 | 
			
		||||
 | 
			
		||||
                    int minutesSpent = (int) Duration.between(nearestSchedule.getFinishedTime(), timeReference).toMinutes();
 | 
			
		||||
                    task.increaseActiveTime(minutesSpent);
 | 
			
		||||
                    BasicTaskSchedule basicTaskSchedule = new BasicTaskSchedule(task, timeReference.toLocalDate());
 | 
			
		||||
                    basicTaskSchedule.setStartTime(nearestSchedule.getFinishedTime());
 | 
			
		||||
                    basicTaskSchedule.setFinishedTime(timeReference);
 | 
			
		||||
                    basicTaskScheduleRepository.save(basicTaskSchedule);
 | 
			
		||||
                    taskRepository.save(task);
 | 
			
		||||
                    return new ServiceResult<>(minutesSpent);
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            case PLANNED -> {
 | 
			
		||||
                //Does not make sense until advanced schedule/moderate schedule is implemented
 | 
			
		||||
                return new ServiceResult<>(0);
 | 
			
		||||
            }
 | 
			
		||||
            default -> {
 | 
			
		||||
                throw new RuntimeException("INVALID MODE");
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -98,4 +98,8 @@ public class TaskService {
 | 
			
		||||
            taskScheduleService.deleteBasicSchedule(deletedTaskSchedule);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public List<Task> loadAllTasks(String username, boolean finished) {
 | 
			
		||||
        return taskRepository.findAllByUser(username, finished);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -17,6 +17,7 @@ model/accountDeleteRequest.ts
 | 
			
		||||
model/basicScheduleEntityInfo.ts
 | 
			
		||||
model/basicScheduleFieldInfo.ts
 | 
			
		||||
model/eMailChangeRequest.ts
 | 
			
		||||
model/forgottenActivityRequest.ts
 | 
			
		||||
model/inlineResponse200.ts
 | 
			
		||||
model/inlineResponse401.ts
 | 
			
		||||
model/inlineResponse403.ts
 | 
			
		||||
 | 
			
		||||
@ -20,6 +20,7 @@ import { Observable }                                        from 'rxjs';
 | 
			
		||||
 | 
			
		||||
import { BasicScheduleEntityInfo } from '../model/models';
 | 
			
		||||
import { BasicScheduleFieldInfo } from '../model/models';
 | 
			
		||||
import { ForgottenActivityRequest } from '../model/models';
 | 
			
		||||
import { ScheduleActivateInfo } from '../model/models';
 | 
			
		||||
import { ScheduleInfo } from '../model/models';
 | 
			
		||||
import { ScheduleStatus } from '../model/models';
 | 
			
		||||
@ -581,6 +582,76 @@ export class ScheduleService {
 | 
			
		||||
        );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * registers forgotten schedule
 | 
			
		||||
     * Registers forgotten schedule
 | 
			
		||||
     * @param taskID internal id of task
 | 
			
		||||
     * @param forgottenActivityRequest 
 | 
			
		||||
     * @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 schedulesTaskIDForgottenPost(taskID: number, forgottenActivityRequest?: ForgottenActivityRequest, observe?: 'body', reportProgress?: boolean, options?: {httpHeaderAccept?: 'application/json', context?: HttpContext}): Observable<TaskScheduleStopResponse>;
 | 
			
		||||
    public schedulesTaskIDForgottenPost(taskID: number, forgottenActivityRequest?: ForgottenActivityRequest, observe?: 'response', reportProgress?: boolean, options?: {httpHeaderAccept?: 'application/json', context?: HttpContext}): Observable<HttpResponse<TaskScheduleStopResponse>>;
 | 
			
		||||
    public schedulesTaskIDForgottenPost(taskID: number, forgottenActivityRequest?: ForgottenActivityRequest, observe?: 'events', reportProgress?: boolean, options?: {httpHeaderAccept?: 'application/json', context?: HttpContext}): Observable<HttpEvent<TaskScheduleStopResponse>>;
 | 
			
		||||
    public schedulesTaskIDForgottenPost(taskID: number, forgottenActivityRequest?: ForgottenActivityRequest, 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 schedulesTaskIDForgottenPost.');
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        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<TaskScheduleStopResponse>(`${this.configuration.basePath}/schedules/${encodeURIComponent(String(taskID))}/forgotten`,
 | 
			
		||||
            forgottenActivityRequest,
 | 
			
		||||
            {
 | 
			
		||||
                context: localVarHttpContext,
 | 
			
		||||
                responseType: <any>responseType_,
 | 
			
		||||
                withCredentials: this.configuration.withCredentials,
 | 
			
		||||
                headers: localVarHeaders,
 | 
			
		||||
                observe: observe,
 | 
			
		||||
                reportProgress: reportProgress
 | 
			
		||||
            }
 | 
			
		||||
        );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * schedule task now
 | 
			
		||||
     * schedule task now
 | 
			
		||||
 | 
			
		||||
@ -22,6 +22,7 @@ import { InlineResponse403 } from '../model/models';
 | 
			
		||||
import { SimpleStatusResponse } from '../model/models';
 | 
			
		||||
import { TaskEntityInfo } from '../model/models';
 | 
			
		||||
import { TaskFieldInfo } from '../model/models';
 | 
			
		||||
import { TaskShortInfo } from '../model/models';
 | 
			
		||||
 | 
			
		||||
import { BASE_PATH, COLLECTION_FORMATS }                     from '../variables';
 | 
			
		||||
import { Configuration }                                     from '../configuration';
 | 
			
		||||
@ -88,6 +89,65 @@ export class TaskService {
 | 
			
		||||
        return httpParams;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * edits an existing task
 | 
			
		||||
     * edits an existing task
 | 
			
		||||
     * @param finished fetches either finished or unfinished 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 tasksAllFinishedGet(finished: boolean, observe?: 'body', reportProgress?: boolean, options?: {httpHeaderAccept?: 'application/json', context?: HttpContext}): Observable<Array<TaskShortInfo>>;
 | 
			
		||||
    public tasksAllFinishedGet(finished: boolean, observe?: 'response', reportProgress?: boolean, options?: {httpHeaderAccept?: 'application/json', context?: HttpContext}): Observable<HttpResponse<Array<TaskShortInfo>>>;
 | 
			
		||||
    public tasksAllFinishedGet(finished: boolean, observe?: 'events', reportProgress?: boolean, options?: {httpHeaderAccept?: 'application/json', context?: HttpContext}): Observable<HttpEvent<Array<TaskShortInfo>>>;
 | 
			
		||||
    public tasksAllFinishedGet(finished: boolean, observe: any = 'body', reportProgress: boolean = false, options?: {httpHeaderAccept?: 'application/json', context?: HttpContext}): Observable<any> {
 | 
			
		||||
        if (finished === null || finished === undefined) {
 | 
			
		||||
            throw new Error('Required parameter finished was null or undefined when calling tasksAllFinishedGet.');
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        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<TaskShortInfo>>(`${this.configuration.basePath}/tasks/all/${encodeURIComponent(String(finished))}`,
 | 
			
		||||
            {
 | 
			
		||||
                context: localVarHttpContext,
 | 
			
		||||
                responseType: <any>responseType_,
 | 
			
		||||
                withCredentials: this.configuration.withCredentials,
 | 
			
		||||
                headers: localVarHeaders,
 | 
			
		||||
                observe: observe,
 | 
			
		||||
                reportProgress: reportProgress
 | 
			
		||||
            }
 | 
			
		||||
        );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * edits an existing task
 | 
			
		||||
     * edits an existing task
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										33
									
								
								frontend/src/api/model/forgottenActivityRequest.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										33
									
								
								frontend/src/api/model/forgottenActivityRequest.ts
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,33 @@
 | 
			
		||||
/**
 | 
			
		||||
 * 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 ForgottenActivityRequest { 
 | 
			
		||||
    /**
 | 
			
		||||
     * mode of register forgotten activity
 | 
			
		||||
     */
 | 
			
		||||
    mode: ForgottenActivityRequest.ModeEnum;
 | 
			
		||||
    /**
 | 
			
		||||
     * number of minutes spent on task
 | 
			
		||||
     */
 | 
			
		||||
    minutesSpent?: number;
 | 
			
		||||
}
 | 
			
		||||
export namespace ForgottenActivityRequest {
 | 
			
		||||
    export type ModeEnum = 'MANUAL' | 'LAST' | 'PLANNED';
 | 
			
		||||
    export const ModeEnum = {
 | 
			
		||||
        Manual: 'MANUAL' as ModeEnum,
 | 
			
		||||
        Last: 'LAST' as ModeEnum,
 | 
			
		||||
        Planned: 'PLANNED' as ModeEnum
 | 
			
		||||
    };
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -2,6 +2,7 @@ export * from './accountDeleteRequest';
 | 
			
		||||
export * from './basicScheduleEntityInfo';
 | 
			
		||||
export * from './basicScheduleFieldInfo';
 | 
			
		||||
export * from './eMailChangeRequest';
 | 
			
		||||
export * from './forgottenActivityRequest';
 | 
			
		||||
export * from './inlineResponse200';
 | 
			
		||||
export * from './inlineResponse401';
 | 
			
		||||
export * from './inlineResponse403';
 | 
			
		||||
 | 
			
		||||
@ -67,6 +67,8 @@ import { ActiveScheduleComponent } from './dashboard/active-schedule/active-sche
 | 
			
		||||
import {MatTreeModule} from "@angular/material/tree";
 | 
			
		||||
import { TaskgroupOverviewComponent } from './dashboard/taskgroup-overview/taskgroup-overview.component';
 | 
			
		||||
import { TaskOverviewComponent } from './dashboard/task-overview/task-overview.component';
 | 
			
		||||
import { ForgottenTaskStartDialogComponent } from './dashboard/forgotten-task-start-dialog/forgotten-task-start-dialog.component';
 | 
			
		||||
import {MatAutocompleteModule} from "@angular/material/autocomplete";
 | 
			
		||||
@NgModule({
 | 
			
		||||
  declarations: [
 | 
			
		||||
    AppComponent,
 | 
			
		||||
@ -97,44 +99,46 @@ import { TaskOverviewComponent } from './dashboard/task-overview/task-overview.c
 | 
			
		||||
    DashboardComponent,
 | 
			
		||||
    ActiveScheduleComponent,
 | 
			
		||||
    TaskgroupOverviewComponent,
 | 
			
		||||
    TaskOverviewComponent
 | 
			
		||||
    TaskOverviewComponent,
 | 
			
		||||
    ForgottenTaskStartDialogComponent
 | 
			
		||||
  ],
 | 
			
		||||
  imports: [
 | 
			
		||||
    BrowserModule,
 | 
			
		||||
    AppRoutingModule,
 | 
			
		||||
    FormsModule,
 | 
			
		||||
    ApiModule,
 | 
			
		||||
    HttpClientModule,
 | 
			
		||||
    BrowserAnimationsModule,
 | 
			
		||||
    MatToolbarModule,
 | 
			
		||||
    MatButtonModule,
 | 
			
		||||
    MatIconModule,
 | 
			
		||||
    MatDialogModule,
 | 
			
		||||
    MatFormFieldModule,
 | 
			
		||||
    MatInputModule,
 | 
			
		||||
    MatProgressSpinnerModule,
 | 
			
		||||
    MatSnackBarModule,
 | 
			
		||||
    MatMenuModule,
 | 
			
		||||
    MatTabsModule,
 | 
			
		||||
    MatTableModule,
 | 
			
		||||
    MatCheckboxModule,
 | 
			
		||||
    MatCardModule,
 | 
			
		||||
    ReactiveFormsModule,
 | 
			
		||||
    MatListModule,
 | 
			
		||||
    MatDatepickerModule,
 | 
			
		||||
    MatInputModule,
 | 
			
		||||
    MatDatepickerModule,
 | 
			
		||||
    MatMomentDateModule,
 | 
			
		||||
    FormsModule,
 | 
			
		||||
    MatSlideToggleModule,
 | 
			
		||||
    MatSortModule,
 | 
			
		||||
    MatPaginatorModule,
 | 
			
		||||
    MatProgressBarModule,
 | 
			
		||||
    MatExpansionModule,
 | 
			
		||||
    CalendarModule.forRoot({provide: DateAdapter, useFactory: adapterFactory}),
 | 
			
		||||
    MatSelectModule,
 | 
			
		||||
    MatTreeModule,
 | 
			
		||||
    MatAutocompleteModule
 | 
			
		||||
  ],
 | 
			
		||||
    imports: [
 | 
			
		||||
        BrowserModule,
 | 
			
		||||
        AppRoutingModule,
 | 
			
		||||
        FormsModule,
 | 
			
		||||
        ApiModule,
 | 
			
		||||
        HttpClientModule,
 | 
			
		||||
        BrowserAnimationsModule,
 | 
			
		||||
        MatToolbarModule,
 | 
			
		||||
        MatButtonModule,
 | 
			
		||||
        MatIconModule,
 | 
			
		||||
        MatDialogModule,
 | 
			
		||||
        MatFormFieldModule,
 | 
			
		||||
        MatInputModule,
 | 
			
		||||
        MatProgressSpinnerModule,
 | 
			
		||||
        MatSnackBarModule,
 | 
			
		||||
        MatMenuModule,
 | 
			
		||||
        MatTabsModule,
 | 
			
		||||
        MatTableModule,
 | 
			
		||||
        MatCheckboxModule,
 | 
			
		||||
        MatCardModule,
 | 
			
		||||
        ReactiveFormsModule,
 | 
			
		||||
        MatListModule,
 | 
			
		||||
        MatDatepickerModule,
 | 
			
		||||
        MatInputModule,
 | 
			
		||||
        MatDatepickerModule,
 | 
			
		||||
        MatMomentDateModule,
 | 
			
		||||
        FormsModule,
 | 
			
		||||
        MatSlideToggleModule,
 | 
			
		||||
        MatSortModule,
 | 
			
		||||
        MatPaginatorModule,
 | 
			
		||||
        MatProgressBarModule,
 | 
			
		||||
        MatExpansionModule,
 | 
			
		||||
        CalendarModule.forRoot({provide: DateAdapter, useFactory: adapterFactory}),
 | 
			
		||||
        MatSelectModule,
 | 
			
		||||
        MatTreeModule
 | 
			
		||||
    ],
 | 
			
		||||
  providers: [
 | 
			
		||||
    HttpClientModule,
 | 
			
		||||
    /*
 | 
			
		||||
 | 
			
		||||
@ -1,7 +1,7 @@
 | 
			
		||||
<mat-card class="green-card" *ngIf="activeSchedule == undefined">
 | 
			
		||||
  <mat-card-content>
 | 
			
		||||
    <p>Currently there is no task in progress.</p>
 | 
			
		||||
    <a class="btn-link" routerLink="/">Did you forget to start an activity?</a>
 | 
			
		||||
    <a class="btn-link" (click)="openForgettedActivityDialog()">Did you forget to start an activity?</a>
 | 
			
		||||
  </mat-card-content>
 | 
			
		||||
</mat-card>
 | 
			
		||||
<mat-card *ngIf="activeSchedule != undefined">
 | 
			
		||||
 | 
			
		||||
@ -1,7 +1,9 @@
 | 
			
		||||
import {Component, EventEmitter, Input, OnInit, Output} from '@angular/core';
 | 
			
		||||
import {ScheduleInfo, ScheduleService, TaskOverviewInfo} from "../../../api";
 | 
			
		||||
import {ScheduleInfo, ScheduleService, TaskOverviewInfo, TaskScheduleStopResponse} from "../../../api";
 | 
			
		||||
import {StopActiveScheduleInfo} from "./StopActiveScheduleInfo";
 | 
			
		||||
import {TaskOverviewComponent} from "../task-overview/task-overview.component";
 | 
			
		||||
import {MatDialog} from "@angular/material/dialog";
 | 
			
		||||
import {ForgottenTaskStartDialogComponent} from "../forgotten-task-start-dialog/forgotten-task-start-dialog.component";
 | 
			
		||||
 | 
			
		||||
@Component({
 | 
			
		||||
  selector: 'app-active-schedule',
 | 
			
		||||
@ -16,8 +18,10 @@ export class ActiveScheduleComponent implements OnInit{
 | 
			
		||||
  displayTime: string = "00:00:00"
 | 
			
		||||
 | 
			
		||||
  @Output('onStopTask') scheduleStopEmitter = new EventEmitter<StopActiveScheduleInfo>;
 | 
			
		||||
  @Output('registerForgotten') registerForgottenEmitter = new EventEmitter<TaskScheduleStopResponse>
 | 
			
		||||
 | 
			
		||||
  constructor(private scheduleService: ScheduleService) {
 | 
			
		||||
  constructor(private scheduleService: ScheduleService,
 | 
			
		||||
              private dialog: MatDialog) {
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
  }
 | 
			
		||||
@ -74,4 +78,12 @@ export class ActiveScheduleComponent implements OnInit{
 | 
			
		||||
    this.activeSchedule = undefined
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  openForgettedActivityDialog() {
 | 
			
		||||
    const dialogRef = this.dialog.open(ForgottenTaskStartDialogComponent, {width: "400px"})
 | 
			
		||||
    dialogRef.afterClosed().subscribe(res => {
 | 
			
		||||
      if(res != undefined) {
 | 
			
		||||
        this.registerForgottenEmitter.emit(res);
 | 
			
		||||
      }
 | 
			
		||||
    })
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -8,7 +8,7 @@
 | 
			
		||||
    </mat-card>
 | 
			
		||||
    <h1 class="dashboard-heading">Now<b class="today-worked-info">Today: {{workedMinutesToday}} min</b></h1>
 | 
			
		||||
 | 
			
		||||
    <app-active-schedule #activeSchedule (onStopTask)="stopedTask($event)"></app-active-schedule>
 | 
			
		||||
    <app-active-schedule #activeSchedule (onStopTask)="stopedTask($event)" (registerForgotten)="registerForgotten($event)"></app-active-schedule>
 | 
			
		||||
 | 
			
		||||
    <h1 class="dashboard-heading">Scheduled for today</h1>
 | 
			
		||||
    <mat-card class="green-card" *ngIf="schedules.length == 0">
 | 
			
		||||
 | 
			
		||||
@ -1,5 +1,11 @@
 | 
			
		||||
import {Component, OnInit, ViewChild} from '@angular/core';
 | 
			
		||||
import {BasicScheduleEntityInfo, ScheduleInfo, ScheduleService, TaskOverviewInfo} from "../../api";
 | 
			
		||||
import {
 | 
			
		||||
  BasicScheduleEntityInfo,
 | 
			
		||||
  ScheduleInfo,
 | 
			
		||||
  ScheduleService,
 | 
			
		||||
  TaskOverviewInfo,
 | 
			
		||||
  TaskScheduleStopResponse
 | 
			
		||||
} from "../../api";
 | 
			
		||||
import {ActiveScheduleComponent} from "./active-schedule/active-schedule.component";
 | 
			
		||||
import {StopActiveScheduleInfo} from "./active-schedule/StopActiveScheduleInfo";
 | 
			
		||||
import {TaskOverviewComponent} from "./task-overview/task-overview.component";
 | 
			
		||||
@ -72,4 +78,8 @@ export class DashboardComponent implements OnInit{
 | 
			
		||||
 | 
			
		||||
    this.schedules = this.schedules.filter(schedule => schedule.task.taskID !== task.taskID)
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  registerForgotten(taskScheduleStopResponse: TaskScheduleStopResponse) {
 | 
			
		||||
    this.workedMinutesToday += taskScheduleStopResponse.workTime
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -0,0 +1,4 @@
 | 
			
		||||
.example-full-width {
 | 
			
		||||
  width: 100%;
 | 
			
		||||
  margin-left: 10px;
 | 
			
		||||
}
 | 
			
		||||
@ -0,0 +1,31 @@
 | 
			
		||||
<h1 mat-dialog-title>Register forgotten activity</h1>
 | 
			
		||||
<div mat-dialog-content>
 | 
			
		||||
  <mat-form-field class="example-full-width">
 | 
			
		||||
    <mat-label>Number</mat-label>
 | 
			
		||||
    <input type="text"
 | 
			
		||||
           placeholder="Pick one"
 | 
			
		||||
           matInput
 | 
			
		||||
           [formControl]="myControl"
 | 
			
		||||
           [matAutocomplete]="auto">
 | 
			
		||||
    <mat-autocomplete autoActiveFirstOption #auto="matAutocomplete">
 | 
			
		||||
      <mat-option *ngFor="let option of filteredOptions | async" [value]="option">
 | 
			
		||||
        {{option}}
 | 
			
		||||
      </mat-option>
 | 
			
		||||
    </mat-autocomplete>
 | 
			
		||||
  </mat-form-field>
 | 
			
		||||
 | 
			
		||||
  <mat-checkbox *ngIf="!plannedSchedule" [(ngModel)]="lastSchedule">Automatic starttime based on <b>last</b> schedule</mat-checkbox>
 | 
			
		||||
  <mat-checkbox *ngIf="!lastSchedule" [(ngModel)]="plannedSchedule">Automatic starttime based on <b>planned</b> schedule</mat-checkbox>
 | 
			
		||||
 | 
			
		||||
  <mat-form-field class="example-full-width" *ngIf="!lastSchedule && !plannedSchedule">
 | 
			
		||||
    <mat-label>Minutes spent</mat-label>
 | 
			
		||||
    <input matInput type="number" [formControl]="minutesSpentControl">
 | 
			
		||||
  </mat-form-field>
 | 
			
		||||
</div>
 | 
			
		||||
 | 
			
		||||
<div mat-dialog-actions align="end">
 | 
			
		||||
  <button mat-raised-button>Cancel</button>
 | 
			
		||||
  <button mat-raised-button color="primary" (click)="registerActivity()">Register</button>
 | 
			
		||||
</div>
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -0,0 +1,21 @@
 | 
			
		||||
import { ComponentFixture, TestBed } from '@angular/core/testing';
 | 
			
		||||
 | 
			
		||||
import { ForgottenTaskStartDialogComponent } from './forgotten-task-start-dialog.component';
 | 
			
		||||
 | 
			
		||||
describe('ForgottenTaskStartDialogComponent', () => {
 | 
			
		||||
  let component: ForgottenTaskStartDialogComponent;
 | 
			
		||||
  let fixture: ComponentFixture<ForgottenTaskStartDialogComponent>;
 | 
			
		||||
 | 
			
		||||
  beforeEach(() => {
 | 
			
		||||
    TestBed.configureTestingModule({
 | 
			
		||||
      declarations: [ForgottenTaskStartDialogComponent]
 | 
			
		||||
    });
 | 
			
		||||
    fixture = TestBed.createComponent(ForgottenTaskStartDialogComponent);
 | 
			
		||||
    component = fixture.componentInstance;
 | 
			
		||||
    fixture.detectChanges();
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  it('should create', () => {
 | 
			
		||||
    expect(component).toBeTruthy();
 | 
			
		||||
  });
 | 
			
		||||
});
 | 
			
		||||
@ -0,0 +1,87 @@
 | 
			
		||||
import {Component, OnInit} from '@angular/core';
 | 
			
		||||
import {ForgottenActivityRequest, ScheduleService, 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 {FormControl} from "@angular/forms";
 | 
			
		||||
import ModeEnum = ForgottenActivityRequest.ModeEnum;
 | 
			
		||||
 | 
			
		||||
@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<string[]> | undefined;
 | 
			
		||||
 | 
			
		||||
  lastSchedule: boolean = false
 | 
			
		||||
  plannedSchedule: boolean = false
 | 
			
		||||
  minutesSpentControl: FormControl = new FormControl();
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
  constructor(private taskService: TaskService,
 | 
			
		||||
              private snackbar: MatSnackBar,
 | 
			
		||||
              private dialogRef: MatDialogRef<ForgottenTaskStartDialogComponent>,
 | 
			
		||||
              private scheduleService: ScheduleService) {
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  ngOnInit() {
 | 
			
		||||
    this.taskService.tasksAllFinishedGet(false).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});
 | 
			
		||||
      }
 | 
			
		||||
    })
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  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});
 | 
			
		||||
          }
 | 
			
		||||
        }
 | 
			
		||||
      })
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  private determineRegisterMode(): ModeEnum {
 | 
			
		||||
    if(this.lastSchedule) {
 | 
			
		||||
      return "LAST";
 | 
			
		||||
    } else if(this.plannedSchedule) {
 | 
			
		||||
      return "PLANNED";
 | 
			
		||||
    } else {
 | 
			
		||||
      return "MANUAL";
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										95
									
								
								openapi.yaml
									
									
									
									
									
								
							
							
						
						
									
										95
									
								
								openapi.yaml
									
									
									
									
									
								
							@ -883,6 +883,32 @@ paths:
 | 
			
		||||
              schema:
 | 
			
		||||
                type: object
 | 
			
		||||
                $ref: "#/components/schemas/SimpleStatusResponse"    
 | 
			
		||||
  /tasks/all/{finished}:
 | 
			
		||||
    get:
 | 
			
		||||
      security:
 | 
			
		||||
        - API_TOKEN: []
 | 
			
		||||
      tags:
 | 
			
		||||
        - task
 | 
			
		||||
      summary: edits an existing task
 | 
			
		||||
      description: edits an existing task
 | 
			
		||||
      parameters:
 | 
			
		||||
        - name: finished
 | 
			
		||||
          in: path
 | 
			
		||||
          description: fetches either finished or unfinished tasks
 | 
			
		||||
          required: true
 | 
			
		||||
          schema:
 | 
			
		||||
            type: boolean
 | 
			
		||||
            example: true
 | 
			
		||||
      responses:
 | 
			
		||||
        200:
 | 
			
		||||
          description: Operation successfull
 | 
			
		||||
          content:
 | 
			
		||||
            application/json:
 | 
			
		||||
              schema:
 | 
			
		||||
                type: array
 | 
			
		||||
                items:
 | 
			
		||||
                  $ref: '#/components/schemas/TaskShortInfo'
 | 
			
		||||
 | 
			
		||||
  /tasks/{taskgroupID}/{status}:
 | 
			
		||||
    get: 
 | 
			
		||||
      security:
 | 
			
		||||
@ -1619,7 +1645,55 @@ paths:
 | 
			
		||||
              schema:
 | 
			
		||||
                type: object
 | 
			
		||||
                $ref: "#/components/schemas/SimpleStatusResponse"
 | 
			
		||||
      
 | 
			
		||||
  /schedules/{taskID}/forgotten:
 | 
			
		||||
    post:
 | 
			
		||||
      security:
 | 
			
		||||
        - API_TOKEN: []
 | 
			
		||||
      tags:
 | 
			
		||||
        - schedule
 | 
			
		||||
      description: Registers forgotten schedule
 | 
			
		||||
      summary: registers forgotten schedule
 | 
			
		||||
      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/ForgottenActivityRequest'
 | 
			
		||||
      responses:
 | 
			
		||||
        200:
 | 
			
		||||
          description: Operation successfull
 | 
			
		||||
          content:
 | 
			
		||||
            application/json:
 | 
			
		||||
              schema:
 | 
			
		||||
                $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"
 | 
			
		||||
      
 | 
			
		||||
      
 | 
			
		||||
      
 | 
			
		||||
@ -2140,4 +2214,21 @@ components:
 | 
			
		||||
        missedSchedules:
 | 
			
		||||
          type: boolean
 | 
			
		||||
          description: states whether a schedule was missed or not
 | 
			
		||||
          example: true
 | 
			
		||||
          example: true
 | 
			
		||||
    ForgottenActivityRequest:
 | 
			
		||||
      required:
 | 
			
		||||
        - mode
 | 
			
		||||
      additionalProperties: false
 | 
			
		||||
      properties:
 | 
			
		||||
        mode:
 | 
			
		||||
          type: string
 | 
			
		||||
          description: mode of register forgotten activity
 | 
			
		||||
          example: MANUAL
 | 
			
		||||
          enum:
 | 
			
		||||
            - MANUAL
 | 
			
		||||
            - LAST
 | 
			
		||||
            - PLANNED
 | 
			
		||||
        minutesSpent:
 | 
			
		||||
          type: number
 | 
			
		||||
          description: number of minutes spent on task
 | 
			
		||||
          example: 10
 | 
			
		||||
		Loading…
	
		Reference in New Issue
	
	Block a user