diff --git a/frontend/src/api/api/schedule.service.ts b/frontend/src/api/api/schedule.service.ts new file mode 100644 index 0000000..e160412 --- /dev/null +++ b/frontend/src/api/api/schedule.service.ts @@ -0,0 +1,152 @@ +/** + * API Title + * No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator) + * + * The version of the OpenAPI document: 1.0 + * + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ +/* tslint:disable:no-unused-variable member-ordering */ + +import { Inject, Injectable, Optional } from '@angular/core'; +import { HttpClient, HttpHeaders, HttpParams, + HttpResponse, HttpEvent, HttpParameterCodec, HttpContext + } from '@angular/common/http'; +import { CustomHttpParameterCodec } from '../encoder'; +import { Observable } from 'rxjs'; + +import { BasicScheduleEntityInfo } from '../model/models'; +import { SimpleStatusResponse } from '../model/models'; + +import { BASE_PATH, COLLECTION_FORMATS } from '../variables'; +import { Configuration } from '../configuration'; + + + +@Injectable({ + providedIn: 'root' +}) +export class ScheduleService { + + protected basePath = 'http://localhost:8080/api'; + public defaultHeaders = new HttpHeaders(); + public configuration = new Configuration(); + public encoder: HttpParameterCodec; + + constructor(protected httpClient: HttpClient, @Optional()@Inject(BASE_PATH) basePath: string, @Optional() configuration: Configuration) { + if (configuration) { + this.configuration = configuration; + } + if (typeof this.configuration.basePath !== 'string') { + if (typeof basePath !== 'string') { + basePath = this.basePath; + } + this.configuration.basePath = basePath; + } + this.encoder = this.configuration.encoder || new CustomHttpParameterCodec(); + } + + + private addToHttpParams(httpParams: HttpParams, value: any, key?: string): HttpParams { + if (typeof value === "object" && value instanceof Date === false) { + httpParams = this.addToHttpParamsRecursive(httpParams, value); + } else { + httpParams = this.addToHttpParamsRecursive(httpParams, value, key); + } + return httpParams; + } + + private addToHttpParamsRecursive(httpParams: HttpParams, value?: any, key?: string): HttpParams { + if (value == null) { + return httpParams; + } + + if (typeof value === "object") { + if (Array.isArray(value)) { + (value as any[]).forEach( elem => httpParams = this.addToHttpParamsRecursive(httpParams, elem, key)); + } else if (value instanceof Date) { + if (key != null) { + httpParams = httpParams.append(key, + (value as Date).toISOString().substr(0, 10)); + } else { + throw Error("key may not be null if value is Date"); + } + } else { + Object.keys(value).forEach( k => httpParams = this.addToHttpParamsRecursive( + httpParams, value[k], key != null ? `${key}.${k}` : k)); + } + } else if (key != null) { + httpParams = httpParams.append(key, value); + } else { + throw Error("key may not be null if value is not object or array"); + } + return httpParams; + } + + /** + * gets schedules of task + * gets schedules of task + * @param taskID internal id of task + * @param scheduleType internal id of task + * @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 schedulesTaskIDScheduleTypeGet(taskID: number, scheduleType: 'BASIC' | 'MODERATE' | 'ADVANCED', observe?: 'body', reportProgress?: boolean, options?: {httpHeaderAccept?: 'application/json', context?: HttpContext}): Observable>; + public schedulesTaskIDScheduleTypeGet(taskID: number, scheduleType: 'BASIC' | 'MODERATE' | 'ADVANCED', observe?: 'response', reportProgress?: boolean, options?: {httpHeaderAccept?: 'application/json', context?: HttpContext}): Observable>>; + public schedulesTaskIDScheduleTypeGet(taskID: number, scheduleType: 'BASIC' | 'MODERATE' | 'ADVANCED', observe?: 'events', reportProgress?: boolean, options?: {httpHeaderAccept?: 'application/json', context?: HttpContext}): Observable>>; + public schedulesTaskIDScheduleTypeGet(taskID: number, scheduleType: 'BASIC' | 'MODERATE' | 'ADVANCED', observe: any = 'body', reportProgress: boolean = false, options?: {httpHeaderAccept?: 'application/json', context?: HttpContext}): Observable { + if (taskID === null || taskID === undefined) { + throw new Error('Required parameter taskID was null or undefined when calling schedulesTaskIDScheduleTypeGet.'); + } + if (scheduleType === null || scheduleType === undefined) { + throw new Error('Required parameter scheduleType was null or undefined when calling schedulesTaskIDScheduleTypeGet.'); + } + + 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>(`${this.configuration.basePath}/schedules/${encodeURIComponent(String(taskID))}/${encodeURIComponent(String(scheduleType))}`, + { + context: localVarHttpContext, + responseType: responseType_, + withCredentials: this.configuration.withCredentials, + headers: localVarHeaders, + observe: observe, + reportProgress: reportProgress + } + ); + } + +} diff --git a/frontend/src/api/model/basicScheduleEntityInfo.ts b/frontend/src/api/model/basicScheduleEntityInfo.ts new file mode 100644 index 0000000..4bcb434 --- /dev/null +++ b/frontend/src/api/model/basicScheduleEntityInfo.ts @@ -0,0 +1,32 @@ +/** + * API Title + * No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator) + * + * The version of the OpenAPI document: 1.0 + * + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + + +export interface BasicScheduleEntityInfo { + /** + * internal id of schedule + */ + scheduleID: number; + /** + * date on which the task is scheduled + */ + scheduleDate: string; + /** + * date on which the task schedule was started + */ + startTime: string; + /** + * date on which the tasks schedule was finished + */ + finishedTime: string; +} + diff --git a/frontend/src/api/model/basicScheduleFieldInfo.ts b/frontend/src/api/model/basicScheduleFieldInfo.ts new file mode 100644 index 0000000..41279ef --- /dev/null +++ b/frontend/src/api/model/basicScheduleFieldInfo.ts @@ -0,0 +1,20 @@ +/** + * API Title + * No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator) + * + * The version of the OpenAPI document: 1.0 + * + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + + +export interface BasicScheduleFieldInfo { + /** + * date on which the task is scheduled + */ + scheduleDate: string; +} + diff --git a/frontend/src/app/tasks/task-detail-overview/task-detail-overview.component.css b/frontend/src/app/tasks/task-detail-overview/task-detail-overview.component.css new file mode 100644 index 0000000..70c3167 --- /dev/null +++ b/frontend/src/app/tasks/task-detail-overview/task-detail-overview.component.css @@ -0,0 +1,93 @@ +.container { + margin: 20px auto; + width: 70%; +} + +.spacer { + margin-bottom: 2.5%; +} + + +@media screen and (max-width: 600px) { + .container { + width: 100%; + margin: 20px 10px; + } +} + +.yellowBtn { + background-color: #f39c12; + color: white; + border-radius: 0; +} + +.grayBtn { + background-color: #444444; + color: white; + border-radius: 0; +} + +.greenBtn { + background-color: #00bc8c; + color: white; + border-radius: 0; +} + +.lightBlueBtn { + background-color: #3498db; + color: white; + border-radius: 0; +} + +.borderless-btn { + border-radius: 0; +} + +.progressbar { + color: #00bc8c; + background-color: #20ffc5; +} + +.status-indicator { + width: 20px; + height: 20px; + border-radius: 50%; + margin: 0 auto; + display: inline; + margin-top: 5px; +} + +.task-header { + display: inline-block; + margin-right: 10px; +} + +.example-spacer { + flex: 1 1 auto; +} + +.task-header-container { + display: flex; + flex-direction: row; + justify-content: space-between; + align-items: center; +} + +.left, .right { + display: inline; +} + +.left { + flex-grow: 4; +} + +::ng-deep .mat-mdc-card-header-text { + display: block; + width: 100%; +} + +.small-btn { + font-size: 0.6rem; + background-color: #3498db; + +} diff --git a/frontend/src/app/tasks/task-detail-overview/task-detail-overview.component.html b/frontend/src/app/tasks/task-detail-overview/task-detail-overview.component.html new file mode 100644 index 0000000..66875ad --- /dev/null +++ b/frontend/src/app/tasks/task-detail-overview/task-detail-overview.component.html @@ -0,0 +1,44 @@ +
+ + + + +
+
+
🟢 {{task!.taskName}}
+
+ +
+
+ +
+ +

ETA: {{task!.eta}} Minuten - Deadline: {{task!.deadline}}

+ +
+ +
+
+ + + + + +
+ +
+ +
+ +
+ +
+
+ + + Schedules +
+ +
+
+
diff --git a/frontend/src/app/tasks/task-detail-overview/task-detail-overview.component.spec.ts b/frontend/src/app/tasks/task-detail-overview/task-detail-overview.component.spec.ts new file mode 100644 index 0000000..cb88139 --- /dev/null +++ b/frontend/src/app/tasks/task-detail-overview/task-detail-overview.component.spec.ts @@ -0,0 +1,21 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { TaskDetailOverviewComponent } from './task-detail-overview.component'; + +describe('TaskDetailOverviewComponent', () => { + let component: TaskDetailOverviewComponent; + let fixture: ComponentFixture; + + beforeEach(() => { + TestBed.configureTestingModule({ + declarations: [TaskDetailOverviewComponent] + }); + fixture = TestBed.createComponent(TaskDetailOverviewComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/frontend/src/app/tasks/task-detail-overview/task-detail-overview.component.ts b/frontend/src/app/tasks/task-detail-overview/task-detail-overview.component.ts new file mode 100644 index 0000000..7488a1f --- /dev/null +++ b/frontend/src/app/tasks/task-detail-overview/task-detail-overview.component.ts @@ -0,0 +1,68 @@ +import {Component, OnInit, ViewChild} from '@angular/core'; +import {NavigationLink, NavigationLinkListComponent} from "../../navigation-link-list/navigation-link-list.component"; +import {ActivatedRoute} from "@angular/router"; +import {TaskEntityInfo, TaskgroupEntityInfo, TaskgroupService, TaskService} from "../../../api"; +import {TaskDashboardComponent} from "../task-dashboard/task-dashboard.component"; + +@Component({ + selector: 'app-task-detail-overview', + templateUrl: './task-detail-overview.component.html', + styleUrls: ['./task-detail-overview.component.css'] +}) +export class TaskDetailOverviewComponent implements OnInit { + + defaultNavigationLinkPath: NavigationLink[] = [ + { + linkText: "Dashboard", + routerLink: ['/'] + }, + { + linkText: "Taskgroups", + routerLink: ["/taskgroups"] + } + ] + taskgroups: TaskgroupEntityInfo[] = [] + taskgroup: TaskgroupEntityInfo | undefined + taskgroupPath: TaskgroupEntityInfo[] = [] + taskgroupID: number = -1; + @ViewChild('navLinkList') navLinkListComponent: NavigationLinkListComponent | undefined + + task: TaskEntityInfo | undefined + + constructor(private activatedRoute: ActivatedRoute, + private taskgroupService: TaskgroupService, + private taskService: TaskService) { + } + + ngOnInit(): void { + this.activatedRoute.paramMap.subscribe(params => { + if (params.has('taskgroupID')) { + this.taskgroupID = Number(params.get('taskgroupID')); + this.taskgroupService.taskgroupsTaskgroupIDGet(this.taskgroupID).subscribe({ + next: resp => { + this.taskgroups = resp.children + this.taskgroupPath = resp.ancestors + this.taskgroup = resp.taskgroupInfo; + this.navLinkListComponent!.addNavigationLink(this.taskgroup.taskgroupName, ['/taskgroups', this.taskgroup.taskgroupID.toString()]) + this.taskgroupPath.forEach(taskgroupEntity => { + this.navLinkListComponent!.addNavigationLink(taskgroupEntity.taskgroupName, ['/taskgroups', taskgroupEntity.taskgroupID.toString()]); + }) + } + }) + } + + if(params.has('taskID')) { + this.taskService.tasksTaskIDGet(Number(params.get('taskID'))).subscribe({ + next: resp => { + this.task = resp; + } + }) + } + }); + } + + getStatusOfTask(task: TaskEntityInfo | undefined) { + return "green"; + + } +}