Active tasks
This commit is contained in:
parent
a9c3931ced
commit
ae7550657c
@ -6,15 +6,11 @@
|
|||||||
<component name="ChangeListManager">
|
<component name="ChangeListManager">
|
||||||
<list default="true" id="3a869f59-290a-4ab2-b036-a878ce801bc4" name="Changes" comment="Fix marking finished task as overdue">
|
<list default="true" id="3a869f59-290a-4ab2-b036-a878ce801bc4" name="Changes" comment="Fix marking finished task as overdue">
|
||||||
<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/models/timemanager/tasks/TaskScope.java" beforeDir="false" afterPath="$PROJECT_DIR$/src/main/java/core/api/models/timemanager/tasks/TaskScope.java" afterDir="false" />
|
|
||||||
<change beforePath="$PROJECT_DIR$/src/main/java/core/repositories/timemanager/TaskRepository.java" beforeDir="false" afterPath="$PROJECT_DIR$/src/main/java/core/repositories/timemanager/TaskRepository.java" afterDir="false" />
|
<change beforePath="$PROJECT_DIR$/src/main/java/core/repositories/timemanager/TaskRepository.java" beforeDir="false" afterPath="$PROJECT_DIR$/src/main/java/core/repositories/timemanager/TaskRepository.java" afterDir="false" />
|
||||||
<change beforePath="$PROJECT_DIR$/src/main/java/core/services/TaskService.java" beforeDir="false" afterPath="$PROJECT_DIR$/src/main/java/core/services/TaskService.java" afterDir="false" />
|
<change beforePath="$PROJECT_DIR$/src/main/java/core/services/TaskService.java" beforeDir="false" afterPath="$PROJECT_DIR$/src/main/java/core/services/TaskService.java" afterDir="false" />
|
||||||
<change beforePath="$PROJECT_DIR$/../frontend/src/api/api/task.service.ts" beforeDir="false" afterPath="$PROJECT_DIR$/../frontend/src/api/api/task.service.ts" afterDir="false" />
|
|
||||||
<change beforePath="$PROJECT_DIR$/../frontend/src/app/app-routing.module.ts" beforeDir="false" afterPath="$PROJECT_DIR$/../frontend/src/app/app-routing.module.ts" afterDir="false" />
|
<change beforePath="$PROJECT_DIR$/../frontend/src/app/app-routing.module.ts" beforeDir="false" afterPath="$PROJECT_DIR$/../frontend/src/app/app-routing.module.ts" afterDir="false" />
|
||||||
<change beforePath="$PROJECT_DIR$/../frontend/src/app/app.component.html" beforeDir="false" afterPath="$PROJECT_DIR$/../frontend/src/app/app.component.html" afterDir="false" />
|
<change beforePath="$PROJECT_DIR$/../frontend/src/app/app.component.html" beforeDir="false" afterPath="$PROJECT_DIR$/../frontend/src/app/app.component.html" afterDir="false" />
|
||||||
<change beforePath="$PROJECT_DIR$/../frontend/src/app/app.module.ts" beforeDir="false" afterPath="$PROJECT_DIR$/../frontend/src/app/app.module.ts" afterDir="false" />
|
<change beforePath="$PROJECT_DIR$/../frontend/src/app/app.module.ts" beforeDir="false" afterPath="$PROJECT_DIR$/../frontend/src/app/app.module.ts" afterDir="false" />
|
||||||
<change beforePath="$PROJECT_DIR$/../frontend/src/app/tasks/task-editor/task-editor.component.ts" beforeDir="false" afterPath="$PROJECT_DIR$/../frontend/src/app/tasks/task-editor/task-editor.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" />
|
||||||
@ -329,11 +325,6 @@
|
|||||||
<line>202</line>
|
<line>202</line>
|
||||||
<option name="timeStamp" value="10" />
|
<option name="timeStamp" value="10" />
|
||||||
</line-breakpoint>
|
</line-breakpoint>
|
||||||
<line-breakpoint enabled="true" type="java-line">
|
|
||||||
<url>file://$PROJECT_DIR$/src/main/java/core/services/TaskService.java</url>
|
|
||||||
<line>69</line>
|
|
||||||
<option name="timeStamp" value="13" />
|
|
||||||
</line-breakpoint>
|
|
||||||
</breakpoints>
|
</breakpoints>
|
||||||
</breakpoint-manager>
|
</breakpoint-manager>
|
||||||
</component>
|
</component>
|
||||||
|
@ -32,4 +32,7 @@ public interface TaskRepository extends CrudRepository<Task, Long> {
|
|||||||
|
|
||||||
@Query(value = "SELECT t FROM Task t WHERE t.taskgroup.user.username = ?1 AND t.startDate IS NOT NULL AND t.startDate > ?2 AND t.finished = FALSE")
|
@Query(value = "SELECT t FROM Task t WHERE t.taskgroup.user.username = ?1 AND t.startDate IS NOT NULL AND t.startDate > ?2 AND t.finished = FALSE")
|
||||||
List<Task> findAllUpcoming(String username, LocalDate now);
|
List<Task> findAllUpcoming(String username, LocalDate now);
|
||||||
|
|
||||||
|
@Query(value = "SELECT t FROM Task t WHERE t.taskgroup.user.username = ?1 AND t.startDate IS NULL OR t.startDate <= ?2 AND t.finished = FALSE")
|
||||||
|
List<Task> findAllActive(String username, LocalDate now);
|
||||||
}
|
}
|
||||||
|
@ -112,6 +112,9 @@ public class TaskService {
|
|||||||
case UPCOMING -> {
|
case UPCOMING -> {
|
||||||
return taskRepository.findAllUpcoming(username, LocalDate.now());
|
return taskRepository.findAllUpcoming(username, LocalDate.now());
|
||||||
}
|
}
|
||||||
|
case ACTIVE -> {
|
||||||
|
return taskRepository.findAllActive(username, LocalDate.now());
|
||||||
|
}
|
||||||
default -> {
|
default -> {
|
||||||
return new ArrayList<>();
|
return new ArrayList<>();
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,89 @@
|
|||||||
|
.container {
|
||||||
|
margin: 20px auto;
|
||||||
|
width: 70%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.spacer {
|
||||||
|
margin-bottom: 2.5%;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@media screen and (max-width: 600px) {
|
||||||
|
.container {
|
||||||
|
width: 100%;
|
||||||
|
margin: 20px 10px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.undecorated-link {
|
||||||
|
text-decoration: none;
|
||||||
|
color: black;
|
||||||
|
}
|
||||||
|
|
||||||
|
.undecorated-link:hover {
|
||||||
|
color: #3498db;
|
||||||
|
}
|
||||||
|
|
||||||
|
.originally-planned-container {
|
||||||
|
border-style: solid;
|
||||||
|
border-color: #e1e1e1;
|
||||||
|
border-width: 1px;
|
||||||
|
margin-top: 10px;
|
||||||
|
border-radius: 5px;
|
||||||
|
padding: 10px;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
.reschedule-actions-container {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
flex-direction: row;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-group {
|
||||||
|
display: inline-block;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.yellowBtn {
|
||||||
|
background-color: #f39c12;
|
||||||
|
color: white;
|
||||||
|
border-radius: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.greenBtn {
|
||||||
|
background-color: #00bc8c;
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-group-item {
|
||||||
|
border-radius: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-group-itemleft {
|
||||||
|
border-top-right-radius: 0;
|
||||||
|
border-bottom-right-radius: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-group-itemright {
|
||||||
|
border-bottom-left-radius: 0;
|
||||||
|
border-top-left-radius: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.grayBtn {
|
||||||
|
background-color: #444444;
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
|
||||||
|
.overdue-warning {
|
||||||
|
background-color: orange;
|
||||||
|
color: white;
|
||||||
|
padding: 10px;
|
||||||
|
border-radius: 6px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.progress-bar {
|
||||||
|
margin-top: 20px;
|
||||||
|
margin-bottom: 20px;
|
||||||
|
}
|
@ -0,0 +1,33 @@
|
|||||||
|
<div class="container">
|
||||||
|
<app-navigation-link-list [navigationLinks]="defaultNavigationLinkPath"></app-navigation-link-list>
|
||||||
|
|
||||||
|
<mat-card *ngFor="let task of tasks">
|
||||||
|
<mat-card-content>
|
||||||
|
<h3>
|
||||||
|
<span *ngFor="let taskgroup of task.taskgroups">
|
||||||
|
<a class="undecorated-link" [routerLink]="['/taskgroups', taskgroup.taskgroupID]">{{taskgroup.taskgroupName}}</a> /
|
||||||
|
</span>
|
||||||
|
<a class="undecorated-link" [routerLink]="['/taskgroups', task.taskgroups[task.taskgroups.length-1].taskgroupID, 'tasks', task.taskID]">{{task.taskName}}</a>
|
||||||
|
</h3>
|
||||||
|
<div class="overdue-warning" *ngIf="task.overdue">
|
||||||
|
<b>This task is overdue!</b>
|
||||||
|
</div>
|
||||||
|
<mat-progress-bar class="progress-bar" mode="determinate" [value]="calcProgress(task)"></mat-progress-bar>
|
||||||
|
<div class="originally-planned-container">
|
||||||
|
<p *ngIf="task.eta != undefined"><i>ETA: </i> {{task.eta}} Minutes</p>
|
||||||
|
<p *ngIf="task.deadline != undefined"><i>Deadline: </i> {{task.deadline}}</p>
|
||||||
|
<div class="reschedule-actions-container">
|
||||||
|
<div class="btn-group">
|
||||||
|
<button mat-raised-button color="primary" class="btn-group-itemleft" [routerLink]="['/taskgroups', task.taskgroups[task.taskgroups.length-1].taskgroupID, 'tasks', task.taskID, 'schedule']">Schedule</button>
|
||||||
|
<button mat-raised-button class="yellowBtn btn-group-item" (click)="startTaskNow(task)">Start now</button>
|
||||||
|
<button mat-raised-button class="btn-group-item grayBtn" (click)="editTask(task)">Edit</button>
|
||||||
|
<button mat-raised-button class="btn-group-itemright greenBtn" (click)="finishTask(task)">Finish</button>
|
||||||
|
</div>
|
||||||
|
<div class="btn-group">
|
||||||
|
<button mat-raised-button color="warn" (click)="deleteTask(task)"><mat-icon>delete</mat-icon>Delete</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</mat-card-content>
|
||||||
|
</mat-card>
|
||||||
|
</div>
|
@ -0,0 +1,21 @@
|
|||||||
|
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||||
|
|
||||||
|
import { ActiveTaskOverviewComponent } from './active-task-overview.component';
|
||||||
|
|
||||||
|
describe('ActiveTaskOverviewComponent', () => {
|
||||||
|
let component: ActiveTaskOverviewComponent;
|
||||||
|
let fixture: ComponentFixture<ActiveTaskOverviewComponent>;
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
TestBed.configureTestingModule({
|
||||||
|
declarations: [ActiveTaskOverviewComponent]
|
||||||
|
});
|
||||||
|
fixture = TestBed.createComponent(ActiveTaskOverviewComponent);
|
||||||
|
component = fixture.componentInstance;
|
||||||
|
fixture.detectChanges();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should create', () => {
|
||||||
|
expect(component).toBeTruthy();
|
||||||
|
});
|
||||||
|
});
|
@ -0,0 +1,117 @@
|
|||||||
|
import {Component, OnInit} from '@angular/core';
|
||||||
|
import {NavigationLink} from "../navigation-link-list/navigation-link-list.component";
|
||||||
|
import {ScheduleService, TaskService, TaskTaskgroupInfo} from "../../api";
|
||||||
|
import {MatSnackBar} from "@angular/material/snack-bar";
|
||||||
|
import {Router} from "@angular/router";
|
||||||
|
import {TaskEditorData} from "../tasks/task-editor/TaskEditorData";
|
||||||
|
import {TaskEditorComponent} from "../tasks/task-editor/task-editor.component";
|
||||||
|
import {MatDialog} from "@angular/material/dialog";
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-active-task-overview',
|
||||||
|
templateUrl: './active-task-overview.component.html',
|
||||||
|
styleUrls: ['./active-task-overview.component.css']
|
||||||
|
})
|
||||||
|
export class ActiveTaskOverviewComponent implements OnInit{
|
||||||
|
tasks: TaskTaskgroupInfo[] = []
|
||||||
|
defaultNavigationLinkPath: NavigationLink[] = [
|
||||||
|
{
|
||||||
|
linkText: "Dashboard",
|
||||||
|
routerLink: ['/']
|
||||||
|
},
|
||||||
|
{
|
||||||
|
linkText: "Active Tasks",
|
||||||
|
routerLink: ["/active"]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
||||||
|
constructor(private taskService: TaskService,
|
||||||
|
private snackbar: MatSnackBar,
|
||||||
|
private scheduleService: ScheduleService,
|
||||||
|
private router: Router,
|
||||||
|
private dialog: MatDialog) {
|
||||||
|
}
|
||||||
|
|
||||||
|
ngOnInit(): void {
|
||||||
|
this.taskService.tasksAllScopeDetailedGet("ACTIVE", true).subscribe({
|
||||||
|
next: resp => {
|
||||||
|
this.tasks = resp as TaskTaskgroupInfo[]
|
||||||
|
},
|
||||||
|
error: err => {
|
||||||
|
if(err.status == 403) {
|
||||||
|
this.snackbar.open("No permissions", "", {duration: 2000});
|
||||||
|
} else if(err.status == 404) {
|
||||||
|
this.snackbar.open("Not found", "", {duration: 2000});
|
||||||
|
} else {
|
||||||
|
this.snackbar.open("Unexpected error", "", {duration: 2000});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
calcProgress(task: TaskTaskgroupInfo): number {
|
||||||
|
console.log(task.workTime / task.eta * 100)
|
||||||
|
return task.workTime / task.eta * 100
|
||||||
|
}
|
||||||
|
|
||||||
|
startTaskNow(task: TaskTaskgroupInfo) {
|
||||||
|
this.scheduleService.schedulesTaskIDNowPost(task.taskID).subscribe({
|
||||||
|
next: resp => {
|
||||||
|
this.router.navigateByUrl("/");
|
||||||
|
},
|
||||||
|
error: err => {
|
||||||
|
if(err.status == 403) {
|
||||||
|
this.snackbar.open("No permissions", "", {duration: 2000});
|
||||||
|
} else if(err.status == 404) {
|
||||||
|
this.snackbar.open("Not found", "", {duration: 2000});
|
||||||
|
} else if(err.status == 409) {
|
||||||
|
this.snackbar.open("Task already running", "", {duration: 2000});
|
||||||
|
} else {
|
||||||
|
this.snackbar.open("Unexpected error", "", {duration: 2000});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
deleteTask(deletedTask: TaskTaskgroupInfo) {
|
||||||
|
this.taskService.tasksTaskIDDelete(deletedTask.taskID).subscribe({
|
||||||
|
next: resp => {
|
||||||
|
this.tasks = this.tasks.filter(task => task.taskID !== deletedTask.taskID);
|
||||||
|
},
|
||||||
|
error: err => {
|
||||||
|
if(err.status == 403) {
|
||||||
|
this.snackbar.open("No permissions", "", {duration: 2000});
|
||||||
|
} else if(err.status == 404) {
|
||||||
|
this.snackbar.open("Not found", "", {duration: 2000});
|
||||||
|
} else {
|
||||||
|
this.snackbar.open("Unexpected error", "", {duration: 2000});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
editTask(editedTask: TaskTaskgroupInfo) {
|
||||||
|
const taskEditorInfo: TaskEditorData = {
|
||||||
|
task: editedTask,
|
||||||
|
taskgroupID: editedTask.taskgroups[editedTask.taskgroups.length-1].taskgroupID
|
||||||
|
};
|
||||||
|
this.dialog.open(TaskEditorComponent, {data: taskEditorInfo, width: "600px"})
|
||||||
|
}
|
||||||
|
|
||||||
|
finishTask(task: TaskTaskgroupInfo) {
|
||||||
|
this.taskService.tasksTaskIDFinishPost(task.taskID).subscribe({
|
||||||
|
next: resp => {
|
||||||
|
this.tasks = this.tasks.filter(t => t.taskID !== task.taskID)
|
||||||
|
},
|
||||||
|
error: err => {
|
||||||
|
if(err.status == 403) {
|
||||||
|
this.snackbar.open("No permissions", "", {duration: 2000});
|
||||||
|
} else if(err.status == 404) {
|
||||||
|
this.snackbar.open("Not found", "", {duration: 2000});
|
||||||
|
} else {
|
||||||
|
this.snackbar.open("Unexpected error", "", {duration: 2000});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
@ -10,6 +10,7 @@ import {SchedulerComponent} from "./schedules/scheduler/scheduler.component";
|
|||||||
import {MissedSchedulesComponent} from "./missed-schedules/missed-schedules.component";
|
import {MissedSchedulesComponent} from "./missed-schedules/missed-schedules.component";
|
||||||
import {OverdueTaskOverviewComponent} from "./overdue-task-overview/overdue-task-overview.component";
|
import {OverdueTaskOverviewComponent} from "./overdue-task-overview/overdue-task-overview.component";
|
||||||
import {UpcomingTaskOverviewComponent} from "./upcoming-task-overview/upcoming-task-overview.component";
|
import {UpcomingTaskOverviewComponent} from "./upcoming-task-overview/upcoming-task-overview.component";
|
||||||
|
import {ActiveTaskOverviewComponent} from "./active-task-overview/active-task-overview.component";
|
||||||
|
|
||||||
const routes: Routes = [
|
const routes: Routes = [
|
||||||
{path: '', component: MainComponent},
|
{path: '', component: MainComponent},
|
||||||
@ -22,7 +23,8 @@ const routes: Routes = [
|
|||||||
{path: 'taskgroups/:taskgroupID/tasks/:taskID/schedule/:scheduleID', component: SchedulerComponent},
|
{path: 'taskgroups/:taskgroupID/tasks/:taskID/schedule/:scheduleID', component: SchedulerComponent},
|
||||||
{path: 'reschedule', component: MissedSchedulesComponent},
|
{path: 'reschedule', component: MissedSchedulesComponent},
|
||||||
{path: 'overdue', component: OverdueTaskOverviewComponent},
|
{path: 'overdue', component: OverdueTaskOverviewComponent},
|
||||||
{path: 'upcoming', component: UpcomingTaskOverviewComponent}
|
{path: 'upcoming', component: UpcomingTaskOverviewComponent},
|
||||||
|
{path: 'active', component: ActiveTaskOverviewComponent}
|
||||||
];
|
];
|
||||||
|
|
||||||
@NgModule({
|
@NgModule({
|
||||||
|
@ -4,6 +4,7 @@
|
|||||||
<button mat-button aria-label="Organize" *ngIf="authService.hasKey" [matMenuTriggerFor]="organizeMenu">Organize ▾</button>
|
<button mat-button aria-label="Organize" *ngIf="authService.hasKey" [matMenuTriggerFor]="organizeMenu">Organize ▾</button>
|
||||||
<mat-menu #organizeMenu=matMenu>
|
<mat-menu #organizeMenu=matMenu>
|
||||||
<button mat-menu-item routerLink="taskgroups/" aria-label="Task groups">Taskgroups</button>
|
<button mat-menu-item routerLink="taskgroups/" aria-label="Task groups">Taskgroups</button>
|
||||||
|
<button mat-menu-item routerLink="active/" aria-label="Missed Schedules">Active Tasks</button>
|
||||||
<button mat-menu-item routerLink="upcoming/" aria-label="Upcoming Tasks">Upcoming Tasks</button>
|
<button mat-menu-item routerLink="upcoming/" aria-label="Upcoming Tasks">Upcoming Tasks</button>
|
||||||
<button mat-menu-item routerLink="overdue/" aria-label="Overdue Tasks">Overdue Tasks</button>
|
<button mat-menu-item routerLink="overdue/" aria-label="Overdue Tasks">Overdue Tasks</button>
|
||||||
<button mat-menu-item routerLink="reschedule/" aria-label="Missed Schedules">Missed Schedules</button>
|
<button mat-menu-item routerLink="reschedule/" aria-label="Missed Schedules">Missed Schedules</button>
|
||||||
|
@ -73,6 +73,7 @@ import { MissedSchedulesComponent } from './missed-schedules/missed-schedules.co
|
|||||||
import { MissedScheduleForgetConfirmationDialogComponent } from './missed-schedules/missed-schedule-forget-confirmation-dialog/missed-schedule-forget-confirmation-dialog.component';
|
import { MissedScheduleForgetConfirmationDialogComponent } from './missed-schedules/missed-schedule-forget-confirmation-dialog/missed-schedule-forget-confirmation-dialog.component';
|
||||||
import { OverdueTaskOverviewComponent } from './overdue-task-overview/overdue-task-overview.component';
|
import { OverdueTaskOverviewComponent } from './overdue-task-overview/overdue-task-overview.component';
|
||||||
import { UpcomingTaskOverviewComponent } from './upcoming-task-overview/upcoming-task-overview.component';
|
import { UpcomingTaskOverviewComponent } from './upcoming-task-overview/upcoming-task-overview.component';
|
||||||
|
import { ActiveTaskOverviewComponent } from './active-task-overview/active-task-overview.component';
|
||||||
@NgModule({
|
@NgModule({
|
||||||
declarations: [
|
declarations: [
|
||||||
AppComponent,
|
AppComponent,
|
||||||
@ -108,7 +109,8 @@ import { UpcomingTaskOverviewComponent } from './upcoming-task-overview/upcoming
|
|||||||
MissedSchedulesComponent,
|
MissedSchedulesComponent,
|
||||||
MissedScheduleForgetConfirmationDialogComponent,
|
MissedScheduleForgetConfirmationDialogComponent,
|
||||||
OverdueTaskOverviewComponent,
|
OverdueTaskOverviewComponent,
|
||||||
UpcomingTaskOverviewComponent
|
UpcomingTaskOverviewComponent,
|
||||||
|
ActiveTaskOverviewComponent
|
||||||
],
|
],
|
||||||
imports: [
|
imports: [
|
||||||
BrowserModule,
|
BrowserModule,
|
||||||
|
Loading…
Reference in New Issue
Block a user