TSK-336 TaskDetails prototype

This commit is contained in:
Lars Leo Grätz 2018-04-30 16:44:35 +02:00 committed by Martin Rojas Miguel Angel
parent 1c93702063
commit 3f23005fa2
23 changed files with 540 additions and 235 deletions

View File

@ -0,0 +1,7 @@
import {Links} from './links';
import {Workbasket} from './workbasket';
export class WorkbasketResource {
constructor(public _embedded: { 'workbaskets': Array<Workbasket> } = { 'workbaskets': [] },
public _links: Links = undefined) {}
}

View File

@ -15,5 +15,9 @@
<h3 class="grey">Select a classification</h3>
<svg-icon class="img-responsive empty-icon" src="./assets/icons/classification-empty.svg"></svg-icon>
</div>
<div *ngIf="currentRoute === 'tasks'" class="center-block no-detail">
<h3 class="grey">Select a Task</h3>
<!--TODO: ICON for task?-->
</div>
</div>
</div>

View File

@ -11,7 +11,8 @@ import { MasterAndDetailService } from 'app/services/masterAndDetail/master-and-
export class MasterAndDetailComponent implements OnInit {
private classifications = 'classifications';
private workbaskets = 'workbaskets';
private detailRoutes: Array<string> = ['/workbaskets/(detail', 'classifications/(detail'];
private tasks = 'tasks';
private detailRoutes: Array<string> = ['/workbaskets/(detail', 'classifications/(detail', 'tasks/(detail'];
private sub: any;
showDetail: Boolean = false;
@ -56,6 +57,8 @@ export class MasterAndDetailComponent implements OnInit {
this.currentRoute = this.workbaskets;
} else if (url.indexOf(this.classifications) !== -1) {
this.currentRoute = this.classifications;
} else if (url.indexOf(this.tasks) !== -1) {
this.currentRoute = this.tasks;
}
}
}

View File

@ -0,0 +1,7 @@
import {Links} from '../../models/links';
import {Task} from './task';
export class TaskResource {
constructor(public _embedded: { 'tasks': Array<Task> } = { 'tasks': [] },
public _links: Links = undefined) {}
}

View File

@ -22,6 +22,21 @@ export class Task {
public priority: number,
public classificationSummaryResource: Classification,
public workbasketSummaryResource: Workbasket,
public custom1: any) {
public custom1: string,
public custom2: string,
public custom3: string,
public custom4: string,
public custom5: string,
public custom6: string,
public custom7: string,
public custom8: string,
public custom9: string,
public custom10: string,
public custom11: string,
public custom12: string,
public custom13: string,
public custom14: string,
public custom15: string,
public custom16: string) {
}
}

View File

@ -1,7 +0,0 @@
import { Injectable } from '@angular/core';
@Injectable()
export class DataService {
workbasketKey: string;
workbasketName: string;
}

View File

@ -1,34 +1,38 @@
import { Task } from '../models/task';
import { Observable } from 'rxjs/Observable';
import { HttpClient, HttpHeaders } from '@angular/common/http';
import { Injectable } from '@angular/core';
import { environment } from 'app/../environments/environment';
import {Task} from 'app/workplace/models/task';
import {Observable} from 'rxjs/Observable';
import {HttpClient} from '@angular/common/http';
import {Injectable} from '@angular/core';
import {environment} from 'app/../environments/environment';
import {TaskResource} from 'app/workplace/models/task-resource';
@Injectable()
export class TaskService {
url = environment.taskanaRestUrl + '/v1/tasks';
url = `${environment.taskanaRestUrl}/v1/tasks`;
constructor(private httpClient: HttpClient) {
}
findTaskWithWorkbaskets(basketKey: string): Observable<Task[]> {
return this.httpClient.get<Task[]>(this.url + '?workbasketId=' + basketKey);
findTasksWithWorkbasket(basketKey: string): Observable<TaskResource> {
return this.httpClient.get<TaskResource>(`${this.url}?workbasket-id=${basketKey}`);
}
getTask(id: string): Observable<Task> {
return this.httpClient.get<Task>(this.url + '/' + id);
return this.httpClient.get<Task>(`${this.url}/${id}`);
}
completeTask(id: string): Observable<Task> {
return this.httpClient.post<Task>(this.url + '/' + id + '/complete', '');
return this.httpClient.post<Task>(`${this.url}/${id}/complete`, '');
}
claimTask(id: string): Observable<Task> {
return this.httpClient.post<Task>(this.url + '/' + id + '/claim', 'test');
return this.httpClient.post<Task>(`${this.url}/${id}/claim`, 'test');
}
transferTask(taskId: string, workbasketKey: string): Observable<Task> {
return this.httpClient.post<Task>(this.url + '/' + taskId
+ '/transfer/' + workbasketKey, '');
return this.httpClient.post<Task>(`${this.url}/${taskId}/transfer/${workbasketKey}`, '');
}
updateTask(task: Task): Observable<Task> {
return this.httpClient.put<Task>(`${this.url}/${task.taskId}`, task);
}
}

View File

@ -1,17 +1,20 @@
import { Injectable } from '@angular/core';
import { Workbasket } from 'app/models/workbasket';
import { environment } from 'app/../environments/environment';
import { Observable } from 'rxjs/Observable';
import { HttpClient, HttpHeaders } from '@angular/common/http';
import { HttpClient } from '@angular/common/http';
import {WorkbasketResource} from 'app/models/workbasket-resource';
@Injectable()
export class WorkbasketService {
url = environment.taskanaRestUrl + '/v1/workbaskets';
url = `${environment.taskanaRestUrl}/v1/workbaskets`;
workbasketKey: string;
workbasketName: string;
constructor(private httpClient: HttpClient) {
}
getAllWorkBaskets(): Observable<Workbasket[]> {
return this.httpClient.get<Workbasket[]>(this.url + '?required-permission=OPEN');
getAllWorkBaskets(): Observable<WorkbasketResource> {
return this.httpClient.get<WorkbasketResource>(`${this.url}?required-permission=OPEN`);
}
}

View File

@ -1,21 +1,52 @@
<nav class="navbar navbar-default">
<div class="container-fluid">
<div class="navbar-header">
<p>
<a class="navbar-brand" href="#">
{{ task?.name }}
</a>
</p>
<taskana-spinner [isRunning]="requestInProgress" ></taskana-spinner>
<div class="panel panel-default">
<div class="panel-heading">
<div class="pull-right">
<div class="col-md-6">
<input class="form-control" auto-complete [(ngModel)]="workbasket" [source]="autoCompleteData"
placeholder="Transfer ..."/>
</div>
<ul class="nav navbar-nav navbar-right">
<li><input class="form-control" auto-complete [(ngModel)]="workbasket" [source]="autoCompleteData" placeholder="Transfer ..." style="margin-top:10px;"/></li>
<li><a><button (click)="transferTask()" class="btn-link"><span title="Transfer task to another workbasket" class="glyphicon glyphicon-new-window text-muted"></span></button></a></li>
<li><a><button (click)="cancelTask()" class="btn-link"><span title="Cancel task and return to task list" class="glyphicon glyphicon-remove-circle text-muted"></span></button></a></li>
<li><a><button (click)="completeTask()" class="btn-link"><span title="Complete task and return to task list" class="glyphicon glyphicon-ok-circle text-success"></span></button></a></li>
</ul>
<button (click)="transferTask()" class="btn-link"><span title="Transfer task to another workbasket"
class="glyphicon glyphicon-new-window text-muted"></span>
</button>
<button (click)="cancelTask()" class="btn-link"><span title="Cancel task and return to task list"
class="glyphicon glyphicon-remove-circle text-muted"></span>
</button>
<button (click)="completeTask()" class="btn-link"><span title="Complete task and return to task list"
class="glyphicon glyphicon-ok-circle text-success"></span>
</button>
</div>
<h4 class="panel-header"><b>{{task?.name}}</b></h4>
</div>
</nav>
<div class="container-fluid">
<iframe [src]="link"></iframe>
<div class="panel-body" *ngIf="task">
<form #TaskForm="ngForm">
<div class="col-md-6">
<div class="form-group">
<label for="task-description" class="control-label">Description</label>
<textarea class="form-control" disabled rows="5" id="task-description" placeholder="Description"
[(ngModel)]="task.description"
name="task.description"></textarea>
</div>
</div>
<div class="col-md-6">
<div class="form-group">
<label for="task-note" class="control-label">Note</label>
<input type="text" disabled class="form-control" id="task-note" placeholder="Task has no Note"
[(ngModel)]="task.note"
name="task.note">
</div>
<div class="form-group">
<label for="task-due" class="control-label">Due Date</label>
<input type="text" disabled class="form-control" id="task-due" placeholder="No deadline set"
[(ngModel)]="task.due"
name="task.due">
</div>
</div>
</form>
</div>
</div>
<iframe [src]="link"></iframe>

View File

@ -1,10 +1,10 @@
import { Component, OnInit } from '@angular/core';
import { ActivatedRoute, Router } from '@angular/router';
import { Task } from '../models/task';
import { Workbasket } from 'app/models/workbasket';
import { DomSanitizer, SafeResourceUrl } from '@angular/platform-browser';
import { TaskService } from '../services/task.service';
import { WorkbasketService } from '../services/workbasket.service';
import {Component, OnInit} from '@angular/core';
import {ActivatedRoute, Router} from '@angular/router';
import {Task} from 'app/workplace/models/task';
import {Workbasket} from 'app/models/workbasket';
import {DomSanitizer, SafeResourceUrl} from '@angular/platform-browser';
import {TaskService} from 'app/workplace/services/task.service';
import {WorkbasketService} from 'app/workplace/services/workbasket.service';
@Component({
@ -13,15 +13,14 @@ import { WorkbasketService } from '../services/workbasket.service';
styleUrls: ['./task.component.scss']
})
export class TaskComponent implements OnInit {
task: Task = null;
link: SafeResourceUrl = this.sanitizer.bypassSecurityTrustResourceUrl('https://duckduckgo.com/?q=');
address = 'https://bing.com';
link: SafeResourceUrl = this.sanitizer.bypassSecurityTrustResourceUrl(this.address);
autoCompleteData: string[] = [];
workbasket: string = null;
workbasketKey: string;
workbaskets: Workbasket[];
private sub: any;
requestInProgress = false;
constructor(private taskService: TaskService,
private workbasketService: WorkbasketService,
@ -32,12 +31,18 @@ export class TaskComponent implements OnInit {
ngOnInit() {
const id = this.route.snapshot.params['id'];
this.getTask(id);
}
getTask(id: string) {
this.requestInProgress = true;
this.taskService.getTask(id).subscribe(
t => {
this.task = t;
this.link = this.sanitizer.bypassSecurityTrustResourceUrl('https://duckduckgo.com/?q=' + this.task.name);
this.workbasketService.getAllWorkBaskets().subscribe(w => {
this.workbaskets = w['_embedded']['workbaskets'];
task => {
this.requestInProgress = false;
this.task = task;
this.link = this.sanitizer.bypassSecurityTrustResourceUrl(`${this.address}/?q=${this.task.name}`);
this.workbasketService.getAllWorkBaskets().subscribe(workbaskets => {
this.workbaskets = workbaskets._embedded ? workbaskets._embedded.workbaskets : [];
this.workbaskets.forEach(workbasket => {
if (workbasket.key !== this.task.workbasketSummaryResource.key) {
this.autoCompleteData.push(workbasket.name);
@ -54,8 +59,11 @@ export class TaskComponent implements OnInit {
this.workbasketKey = workbasket.key;
}
});
this.requestInProgress = true;
this.taskService.transferTask(this.task.taskId, this.workbasketKey).subscribe(
task => {
this.requestInProgress = false;
this.task = task
});
this.navigateBack();
@ -67,14 +75,16 @@ export class TaskComponent implements OnInit {
}
completeTask() {
this.requestInProgress = true;
this.taskService.completeTask(this.task.taskId).subscribe(
task => {
this.requestInProgress = false;
this.task = task
});
this.navigateBack();
}
private navigateBack() {
this.router.navigate(['./'], { relativeTo: this.route.parent });
this.router.navigate([{outlets: {detail: `taskdetail/${this.task.taskId}`}}], {relativeTo: this.route.parent});
}
}

View File

@ -1,29 +1,222 @@
<div *ngIf="task != null" class="panel panel-primary">
<taskana-spinner [isRunning]="requestInProgress" ></taskana-spinner>
<div class="panel panel-default" *ngIf="task">
<div class="panel-heading">
<div class="col-xs-2">
<a type="button" class="glyphicon glyphicon-arrow-left white" (click)="goBack()"></a>
<div class="pull-right">
<button type="button" title="Open task to work on it" class="btn btn-default" aria-label="Left Align"
(click)="openTask(task.taskId)">
<span class="glyphicon glyphicon-new-window" aria-hidden="true"></span>
</button>
<button type="button" title="Update Task" class="btn btn-default" (click)="updateTask()">
<span class="glyphicon glyphicon-saved" aria-hidden="true"></span>
</button>
</div>
Details for task '{{ task.name }}' (ID={{ task.taskId }})
<h4 class="panel-header"><b>{{task?.name}}</b></h4>
</div>
<div class="panel-body">
<p>{{ task.description }}</p>
<p><b>Owner:</b> {{ task.owner }}</p>
<p><b>State:</b> {{ task.state }}</p>
<p><b>Creation Date:</b> {{ task.created | date:'medium' }}</p>
<p><b>Claim Date:</b> {{ task.claimed | date:'medium' }}</p>
<p><b>Completion Date:</b> {{ task.completed | date:'medium' }}</p>
<p><b>Modification Date:</b> {{ task.modified | date:'medium' }}</p>
<p><b>Planning Date:</b> {{ task.planned | date:'medium' }}</p>
<p><b>Due Date:</b> {{ task.due | date:'medium' }}</p>
<p><b>Priority:</b> {{ task.priority }}</p>
<p><b>Creator:</b> {{task.creator}}</p>
<p><b>Note:</b> {{task.note}}</p>
<p><b>Workbasket:</b> {{ task.workbasketSummaryResource.workbasketId }}</p>
<p><b>Classification:</b> {{task.classificationSummaryResource.classificationId}}</p>
<p><b>BusinessProcessID:</b> {{task.businessProcessId}}</p>
<p><b>ParentBusinessProcessID:</b> {{task.parentBusinessProcessId}}</p>
<p><b>Read:</b> {{task.read}}</p>
<p><b>Transferred:</b> {{task.transferred}}</p>
<p><b>custom1:</b> {{task.custom1}}</p>
<div class="panel-body list-group">
<form #TaskForm="ngForm">
<div class="col-md-6">
<div class="form-group">
<label for="task-description" class="control-label">Description</label>
<input type="text" class="form-control" id="task-description" placeholder="Description"
[(ngModel)]="task.description"
name="task.description">
</div>
<div class="form-group">
<label for="task-owner" class="control-label">Owner</label>
<input type="text" class="form-control" id="task-owner" placeholder="Owner" [(ngModel)]="task.owner"
name="task.owner">
</div>
<div class="form-group">
<label for="task-created" class="control-label">Creation Date</label>
<input type="text" disabled class="form-control" id="task-created" [(ngModel)]="task.created"
name="task.created">
</div>
<div class="form-group">
<label for="task-claimed" class="control-label">Claim Date</label>
<input type="text" disabled class="form-control" id="task-claimed" placeholder="Not claimed yet"
[(ngModel)]="task.claimed"
name="task.claimed">
</div>
<div class="form-group">
<label for="task-completed" class="control-label">Completion Date</label>
<input type="text" disabled class="form-control" id="task-completed" placeholder="Not completed yet"
[(ngModel)]="task.completed"
name="task.completed">
</div>
<div class="form-group">
<label for="task-modified" class="control-label">Modification Date</label>
<input type="text" disabled class="form-control" id="task-modified" placeholder="Has not been modified"
[(ngModel)]="task.modified"
name="task.modified">
</div>
<div class="form-group">
<label for="task-planned" class="control-label">Planned Date</label>
<input type="text" disabled class="form-control" id="task-planned" placeholder="No plan set"
[(ngModel)]="task.planned"
name="task.planned">
</div>
<div class="form-group">
<label for="task-due" class="control-label">Due Date</label>
<input type="text" disabled class="form-control" id="task-due" placeholder="No deadline set"
[(ngModel)]="task.due"
name="task.due">
</div>
<div class="form-group">
<label for="task-priority" class="control-label">Priority</label>
<input type="text" class="form-control" id="task-priority" placeholder="no priotity set"
[(ngModel)]="task.priority"
name="task.priority">
</div>
<div class="form-group">
<label for="task-state" class="control-label">State</label>
<input type="text" disabled class="form-control" id="task-state" placeholder="Task has no State"
[(ngModel)]="task.state"
name="task.state">
</div>
<div class="form-group">
<label for="task-note" class="control-label">Note</label>
<input type="text" class="form-control" id="task-note" placeholder="Task has no Note" [(ngModel)]="task.note"
name="task.note">
</div>
<div class="form-group">
<label for="task-workbasket" class="control-label">Workbasket ID</label>
<input type="text" disabled class="form-control" id="task-workbasket"
placeholder="Task does not belong to a Workbasket"
[(ngModel)]="task.workbasketSummaryResource.workbasketId"
name="task.workbasket">
</div>
<div class="form-group">
<label for="task-classification" class="control-label">Classification ID</label>
<input type="text" disabled class="form-control" id="task-classification"
placeholder="Task does not belong to a Classification"
[(ngModel)]="task.classificationSummaryResource.classificationId"
name="task.classification">
</div>
<div class="form-group">
<label for="task-businessProcessId" class="control-label">Business Process ID</label>
<input type="text" disabled class="form-control" id="task-businessProcessId" placeholder="Task has no BPI"
[(ngModel)]="task.businessProcessId"
name="task.businessProcessId">
</div>
<div class="form-group">
<label for="task-parentBusinessProcessId" class="control-label">Parent Business Process ID</label>
<input type="text" disabled class="form-control" id="task-parentBusinessProcessId"
placeholder="Task has no PBPI"
[(ngModel)]="task.businessProcessId"
name="task.parentBusinessProcessId">
</div>
<div class="form-group">
<label for="task-read" class="control-label">Task Read?</label>
<input type="text" disabled class="form-control" id="task-read" placeholder="Task not been read"
[(ngModel)]="task.read"
name="task.read">
</div>
<div class="form-group">
<label for="task-transferred" class="control-label">Task Transferred?</label>
<input type="text" disabled class="form-control" id="task-transferred" placeholder="Task not been transferred"
[(ngModel)]="task.transferred"
name="task.transferred">
</div>
</div>
<div class="col-md-6">
<div class="form-group">
<label for="task-custom1" class="control-label">Custom1</label>
<input type="text" class="form-control" id="task-custom1" placeholder="No custom1 set"
[(ngModel)]="task.custom1"
name="task.custom1">
</div>
<div class="form-group">
<label for="task-custom2" class="control-label">Custom2</label>
<input type="text" class="form-control" id="task-custom2" placeholder="No custom2 set"
[(ngModel)]="task.custom2"
name="task.custom2">
</div>
<div class="form-group">
<label for="task-custom3" class="control-label">Custom3</label>
<input type="text" class="form-control" id="task-custom3" placeholder="No custom3 set"
[(ngModel)]="task.custom3"
name="task.custom3">
</div>
<div class="form-group">
<label for="task-custom4" class="control-label">Custom4</label>
<input type="text" class="form-control" id="task-custom4" placeholder="No custom4 set"
[(ngModel)]="task.custom4"
name="task.custom4">
</div>
<div class="form-group">
<label for="task-custom5" class="control-label">Custom5</label>
<input type="text" class="form-control" id="task-custom5" placeholder="No custom5 set"
[(ngModel)]="task.custom5"
name="task.custom5">
</div>
<div class="form-group">
<label for="task-custom6" class="control-label">Custom6</label>
<input type="text" class="form-control" id="task-custom6" placeholder="No custom6 set"
[(ngModel)]="task.custom6"
name="task.custom6">
</div>
<div class="form-group">
<label for="task-custom7" class="control-label">Custom7</label>
<input type="text" class="form-control" id="task-custom7" placeholder="No custom7 set"
[(ngModel)]="task.custom7"
name="task.custom7">
</div>
<div class="form-group">
<label for="task-custom8" class="control-label">Custom8</label>
<input type="text" class="form-control" id="task-custom8" placeholder="No custom8 set"
[(ngModel)]="task.custom8"
name="task.custom8">
</div>
<div class="form-group">
<label for="task-custom9" class="control-label">Custom9</label>
<input type="text" class="form-control" id="task-custom9" placeholder="No custom9 set"
[(ngModel)]="task.custom9"
name="task.custom9">
</div>
<div class="form-group">
<label for="task-custom10" class="control-label">Custom10</label>
<input type="text" class="form-control" id="task-custom10" placeholder="No custom10 set"
[(ngModel)]="task.custom10"
name="task.custom10">
</div>
<div class="form-group">
<label for="task-custom11" class="control-label">Custom11</label>
<input type="text" class="form-control" id="task-custom11" placeholder="No custom11 set"
[(ngModel)]="task.custom11"
name="task.custom11">
</div>
<div class="form-group">
<label for="task-custom12" class="control-label">Custom12</label>
<input type="text" class="form-control" id="task-custom12" placeholder="No custom12 set"
[(ngModel)]="task.custom12"
name="task.custom12">
</div>
<div class="form-group">
<label for="task-custom13" class="control-label">Custom13</label>
<input type="text" class="form-control" id="task-custom13" placeholder="No custom13 set"
[(ngModel)]="task.custom13"
name="task.custom13">
</div>
<div class="form-group">
<label for="task-custom14" class="control-label">Custom14</label>
<input type="text" class="form-control" id="task-custom14" placeholder="No custom14 set"
[(ngModel)]="task.custom14"
name="task.custom14">
</div>
<div class="form-group">
<label for="task-custom15" class="control-label">Custom15</label>
<input type="text" class="form-control" id="task-custom15" placeholder="No custom15 set"
[(ngModel)]="task.custom15"
name="task.custom15">
</div>
<div class="form-group">
<label for="task-custom16" class="control-label">Custom16</label>
<input type="text" class="form-control" id="task-custom16" placeholder="No custom16 set"
[(ngModel)]="task.custom16"
name="task.custom16">
</div>
</div>
</form>
</div>
</div>

View File

@ -0,0 +1,6 @@
.list-group {
max-height: 84vh;
margin-bottom: 10px;
overflow:scroll;
-webkit-overflow-scrolling: touch;
}

View File

@ -1,8 +1,8 @@
import {Component, OnInit} from '@angular/core';
import {Task} from '../models/task';
import {ActivatedRoute} from '@angular/router';
import {ActivatedRoute, Router} from '@angular/router';
import {TaskService} from '../services/task.service';
import {Location} from '@angular/common';
import {Subscription} from 'rxjs/Subscription';
@Component({
selector: 'taskana-task-details',
@ -11,24 +11,39 @@ import {Location} from '@angular/common';
})
export class TaskdetailsComponent implements OnInit {
task: Task = null;
requestInProgress = false;
private routeSubscription: Subscription;
constructor(private route: ActivatedRoute,
private taskService: TaskService,
private location: Location) {
private router: Router) {
}
ngOnInit() {
this.getTask();
}
getTask(): void {
const id = this.route.snapshot.paramMap.get('id');
this.taskService.getTask(id).subscribe(task => {
this.task = task
this.routeSubscription = this.route.params.subscribe(params => {
const id = params['id'];
this.getTask(id);
});
}
goBack(): void {
this.location.back();
getTask(id: string): void {
this.requestInProgress = true;
this.taskService.getTask(id).subscribe(task => {
this.requestInProgress = false;
this.task = task;
});
}
updateTask() {
this.requestInProgress = true;
this.taskService.updateTask(this.task).subscribe(task => {
this.requestInProgress = false;
this.task = task;
});
}
openTask(taskId: string) {
this.router.navigate([{outlets: {detail: `task/${taskId}`}}], {relativeTo: this.route.parent});
}
}

View File

@ -1,29 +1,22 @@
<table class="table table-hover">
<thead>
<tr>
<th class="clickable" (click)="orderTasks('id')">ID</th>
<th class="clickable" (click)="orderTasks('name')">Name</th>
<th class="clickable" (click)="orderTasks('due')">Due Date</th>
<th class="clickable" (click)="orderTasks('priority')">Priority</th>
<th class="clickable" (click)="orderTasks('state')">State</th>
<th>Actions</th>
</tr>
</thead>
<tr *ngFor="let task of tasks">
<td>{{ task.taskId }}</td>
<td>{{ task.name }}</td>
<td>{{ task.due | date:'medium' }}</td>
<td>{{ task.priority }}</td>
<td>{{ task.state }}</td>
<td>
<button type="button" title="Open task to work on it" class="btn btn-default" aria-label="Left Align"
(click)="openTask(task.taskId)">
<span class="glyphicon glyphicon-new-window" aria-hidden="true"></span>
</button>
<a type="button" title="View details for task" class="btn btn-default" aria-label="Left Align"
routerLink="taskdetail/{{task.taskId}}">
<span class="glyphicon glyphicon-info-sign" aria-hidden="true"></span>
</a>
</td>
</tr>
</table>
<div class="task-list-full-height">
<taskana-workbasket-selector (tasksChanged)="loadTasks($event)"></taskana-workbasket-selector>
<!--TODO: add toolbar for sorting, also add pagination-->
<div>
<ul #taskList id="task-list-container" class="list-group">
<li class="list-group-item" *ngIf="tasks === undefined || tasks.length === 0" type="text"> There are no Tasks for this workbasket </li>
<li class="list-group-item" *ngFor="let task of tasks" [class.active]="task.taskId == selectedId"
type="text" (click)="selectTask(task.taskId)">
<div class="row">
<dl class="col-xs-10">
<dt data-toggle="tooltip" title="{{task.name}}">{{task.name}},
<i data-toggle="tooltip" title="{{task.taskId}}">{{task.taskId}} </i>
</dt>
<dd data-toggle="tooltip" title="{{task.due}}">Due: {{task.due}} &nbsp;</dd>
<dd data-toggle="tooltip" title="{{task.priority}}">Priority: {{task.priority}} &nbsp;</dd>
<dd data-toggle="tooltip" title="{{task.state}}">State: {{task.state}} &nbsp;</dd>
</dl>
</div>
</li>
</ul>
</div>
</div>

View File

@ -1,3 +1,52 @@
.clickable {
cursor: pointer;
}
.task-list-full-height{
height: calc(100vh - 55px);
}
.row.list-group {
margin-left: 2px;
}
.list-group > li {
border-left: none;
border-right: none;
}
ul {
max-height: 90vh;
margin-bottom: 10px;
overflow:scroll;
-webkit-overflow-scrolling: touch;
}
a > label{
height: 2em;
width: 100%;
}
dd, dt {
text-overflow: ellipsis;
white-space: nowrap;
overflow: hidden;
}
dt > i {
font-weight: normal;
text-overflow: ellipsis;
white-space: nowrap;
overflow: hidden;
}
li > div.row > dl {
margin-bottom: 0px;
}
li > div.row > dl:first-child {
margin-left: 10px;
}
.no-space {
border-top: none;
padding: 0px
}

View File

@ -11,6 +11,7 @@ export class TasklistComponent implements OnInit {
private columnForOrdering: string;
selectedId = '';
@Input() tasks: Task[];
constructor(private router: Router,
@ -25,7 +26,12 @@ export class TasklistComponent implements OnInit {
this.columnForOrdering = column;
}
openTask(id: string) {
this.router.navigate(['tasks/', id], {relativeTo: this.route.parent});
loadTasks(tasks: Task[]) {
this.tasks = tasks;
}
selectTask(taskId: string) {
this.selectedId = taskId;
this.router.navigate([{outlets: {detail: `taskdetail/${this.selectedId}`}}], {relativeTo: this.route});
}
}

View File

@ -1,10 +0,0 @@
<div class="container-fluid">
<div class="row form-group">
<taskana-workbasket-selector (tasksChanged)="loadTasks($event)"></taskana-workbasket-selector>
</div>
<div *ngIf="tasks?.length > 0" class="row form-group">
<div class="col-md-6">
<taskana-task-list [tasks]="tasks" (task)="selectTask($event)"></taskana-task-list>
</div>
</div>
</div>

View File

@ -1,3 +0,0 @@
.container-fluid > .row {
min-height: 50px;
}

View File

@ -1,25 +0,0 @@
import {Component, Input} from '@angular/core';
import {Task} from '../models/task';
@Component({
selector: 'taskana-tasks',
templateUrl: './tasks.component.html',
styleUrls: ['./tasks.component.scss']
})
export class TasksComponent {
@Input()
tasks: Task[];
@Input()
task: Task;
loadTasks(tasks: Task[]) {
this.tasks = tasks;
}
selectTask(task: Task) {
this.task = task;
}
}

View File

@ -1,5 +1,5 @@
<div class="row">
<div class="col-lg-6">
<div class="col-md-12">
<div class="input-group">
<input class="form-control dropdown-toggle" auto-complete [(ngModel)]="result" [source]="autoCompleteData"
placeholder="Search for Workbasket ..."/>

View File

@ -1,9 +1,8 @@
import { Component, EventEmitter, OnInit, Output } from '@angular/core';
import { DataService } from '../services/data.service';
import { Task } from '../models/task';
import { Workbasket } from 'app/models/workbasket';
import { TaskService } from '../services/task.service';
import { WorkbasketService } from '../services/workbasket.service';
import {Component, EventEmitter, OnInit, Output} from '@angular/core';
import {Task} from 'app/workplace/models/task';
import {Workbasket} from 'app/models/workbasket';
import {TaskService} from 'app/workplace/services/task.service';
import {WorkbasketService} from 'app/workplace/services/workbasket.service';
@Component({
selector: 'taskana-workbasket-selector',
@ -22,20 +21,19 @@ export class SelectorComponent implements OnInit {
workbaskets: Workbasket[];
constructor(private taskService: TaskService,
private workbasketService: WorkbasketService,
private dataService: DataService) {
private workbasketService: WorkbasketService) {
}
ngOnInit() {
this.workbasketService.getAllWorkBaskets().subscribe(w => {
this.workbaskets = w['_embedded']['workbaskets'];
this.workbasketService.getAllWorkBaskets().subscribe(workbaskets => {
this.workbaskets = workbaskets._embedded ? workbaskets._embedded.workbaskets : [];
this.workbaskets.forEach(workbasket => {
this.autoCompleteData.push(workbasket.name);
});
});
if (this.dataService.workbasketKey) {
this.getTasks(this.dataService.workbasketKey);
this.result = this.dataService.workbasketName;
if (this.workbasketService.workbasketKey) {
this.getTasks(this.workbasketService.workbasketKey);
this.result = this.workbasketService.workbasketName;
}
}
@ -47,16 +45,20 @@ export class SelectorComponent implements OnInit {
}
});
this.getTasks(this.resultKey);
this.dataService.workbasketKey = this.resultKey;
this.dataService.workbasketName = this.result;
this.workbasketService.workbasketKey = this.resultKey;
this.workbasketService.workbasketName = this.result;
this.tasksChanged.emit(this.tasks);
}
}
getTasks(workbasketKey: string) {
this.taskService.findTaskWithWorkbaskets(workbasketKey).subscribe(
tasks2 => {
tasks2['_embedded']['tasks'].forEach(e => this.tasks.push(e));
this.taskService.findTasksWithWorkbasket(workbasketKey).subscribe(
tasks => {
if (!tasks || tasks._embedded === undefined) {
this.tasks.length = 0;
return;
}
tasks._embedded.tasks.forEach(e => this.tasks.push(e));
});
}
}

View File

@ -1,36 +1,42 @@
import {NgModule} from '@angular/core';
import {RouterModule, Routes} from '@angular/router';
import {WorkplaceComponent} from './workplace.component'
import {TasksComponent} from 'app/workplace/tasks/tasks.component';
import {TaskComponent} from 'app/workplace/task/task.component';
import {MasterAndDetailComponent} from '../shared/master-and-detail/master-and-detail.component';
import {WorkplaceComponent} from './workplace.component';
import {TaskComponent} from './task/task.component';
import {TaskdetailsComponent} from './taskdetails/taskdetails.component';
import {TasklistComponent} from './tasklist/tasklist.component';
const routes: Routes = [
{
path: 'tasks',
component: MasterAndDetailComponent,
children: [
{
path: '',
component: TasklistComponent,
outlet: 'master'
},
{
path: 'taskdetail/:id',
component: TaskdetailsComponent,
outlet: 'detail'
},
{
path: 'task/:id',
component: TaskComponent,
outlet: 'detail'
}
]
},
{
path: '',
component: WorkplaceComponent,
redirectTo: 'tasks',
pathMatch: 'full'
},
{
path: '',
component: WorkplaceComponent,
children: [
{
path: 'tasks',
component: TasksComponent
},
{
path: 'tasks/:id',
component: TaskComponent
},
{
path: 'tasks/taskdetail/:id',
component: TaskdetailsComponent
}
]
}
];
;
@NgModule({
imports: [RouterModule.forChild(routes)],

View File

@ -1,28 +1,26 @@
import { CommonModule } from '@angular/common';
import { NgModule } from '@angular/core';
import { FormsModule } from '@angular/forms';
import { Ng2AutoCompleteModule } from 'ng2-auto-complete';
import { HttpClientModule, HTTP_INTERCEPTORS } from '@angular/common/http';
import { AngularSvgIconModule } from 'angular-svg-icon';
import { WorkplaceRoutingModule } from './workplace-routing.module';
import { AlertModule } from 'ngx-bootstrap';
import { SharedModule } from 'app/shared/shared.module';
import {CommonModule} from '@angular/common';
import {NgModule} from '@angular/core';
import {FormsModule} from '@angular/forms';
import {Ng2AutoCompleteModule} from 'ng2-auto-complete';
import {HTTP_INTERCEPTORS, HttpClientModule} from '@angular/common/http';
import {AngularSvgIconModule} from 'angular-svg-icon';
import {WorkplaceRoutingModule} from './workplace-routing.module';
import {AlertModule} from 'ngx-bootstrap';
import { WorkplaceComponent } from './workplace.component';
import { SelectorComponent } from './workbasket-selector/workbasket-selector.component';
import { TasklistComponent } from './tasklist/tasklist.component';
import { TaskdetailsComponent } from './taskdetails/taskdetails.component';
import { TaskComponent } from './task/task.component';
import { TasksComponent } from './tasks/tasks.component';
import { CodeComponent } from './components/code/code.component';
import { OrderTasksByPipe } from './util/orderTasksBy.pipe';
import { DataService } from './services/data.service';
import { TaskService } from './services/task.service';
import { WorkbasketService } from './services/workbasket.service';
import { CustomHttpClientInterceptor } from './services/custom-http-interceptor/custom-http-interceptor.service';
import {TaskService} from './services/task.service';
import {WorkbasketService} from './services/workbasket.service';
import {SharedModule} from '../shared/shared.module';
import {CustomHttpClientInterceptor} from './services/custom-http-interceptor/custom-http-interceptor.service';
const MODULES = [
@ -42,7 +40,6 @@ const DECLARATIONS = [
TasklistComponent,
TaskdetailsComponent,
TaskComponent,
TasksComponent,
CodeComponent,
OrderTasksByPipe
];
@ -51,7 +48,6 @@ const DECLARATIONS = [
declarations: DECLARATIONS,
imports: MODULES,
providers: [
DataService,
TaskService,
WorkbasketService,
{