Add filters by priority + highlighting
This commit is contained in:
parent
03e8c96a1e
commit
a81a26d989
@ -1,11 +1,12 @@
|
|||||||
import {sortByNumberAscending, sortByStringAscending} from './sorting.service';
|
import {sortByNumberAscending, sortByStringAscending} from './sorting.service';
|
||||||
|
import {Priority} from './backend.service';
|
||||||
|
|
||||||
export abstract class TableComponentBase<T> {
|
export abstract class TableComponentBase<T> {
|
||||||
public sortBy: string;
|
public sortBy: string;
|
||||||
public sortDescending = false;
|
public sortDescending = false;
|
||||||
public items: T[] = [];
|
public items: T[] = [];
|
||||||
|
|
||||||
protected doNumericSort(by: string, key: (ScrumTask) => number) {
|
protected doNumericSort(by: string, key: (item: T) => number) {
|
||||||
if (this.sortBy === by) {
|
if (this.sortBy === by) {
|
||||||
this.sortDescending = !this.sortDescending;
|
this.sortDescending = !this.sortDescending;
|
||||||
} else {
|
} else {
|
||||||
@ -18,7 +19,7 @@ export abstract class TableComponentBase<T> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected doStringSort(by: string, key: (ScrumTask) => string) {
|
protected doStringSort(by: string, key: (item: T) => string) {
|
||||||
if (this.sortBy === by) {
|
if (this.sortBy === by) {
|
||||||
this.sortDescending = !this.sortDescending;
|
this.sortDescending = !this.sortDescending;
|
||||||
} else {
|
} else {
|
||||||
@ -30,4 +31,8 @@ export abstract class TableComponentBase<T> {
|
|||||||
this.items = this.items.reverse();
|
this.items = this.items.reverse();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public getAllPriorities(): string[] {
|
||||||
|
return Object.values(Priority);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,3 +2,6 @@ table {
|
|||||||
table-layout: fixed;
|
table-layout: fixed;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
th.sortable:hover {
|
||||||
|
text-decoration: underline;
|
||||||
|
}
|
||||||
|
@ -9,6 +9,9 @@
|
|||||||
</a>
|
</a>
|
||||||
Tasks
|
Tasks
|
||||||
</h3>
|
</h3>
|
||||||
|
<div *ngIf="filterUserstoryId">
|
||||||
|
<a [routerLink]="'/tasks'">Alle Tasks anzeigen</a>
|
||||||
|
</div>
|
||||||
|
|
||||||
<button class="btn btn-secondary my-3" (click)="openTaskForm()">Neuer Task</button>
|
<button class="btn btn-secondary my-3" (click)="openTaskForm()">Neuer Task</button>
|
||||||
|
|
||||||
@ -16,37 +19,43 @@
|
|||||||
|
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
<th (click)="sortById()">
|
<th (click)="sortById()" class="sortable">
|
||||||
<span>ID</span>
|
<span>ID</span>
|
||||||
<span *ngIf="sortBy === 'id'" class="pl-3">
|
<span *ngIf="sortBy === 'id'" class="pl-3">
|
||||||
<span *ngIf="sortDescending">▲</span>
|
<span *ngIf="sortDescending">▲</span>
|
||||||
<span *ngIf="sortDescending === false">▼</span>
|
<span *ngIf="sortDescending === false">▼</span>
|
||||||
</span>
|
</span>
|
||||||
</th>
|
</th>
|
||||||
<th (click)="sortByTitle()">
|
<th (click)="sortByTitle()" class="sortable">
|
||||||
<span>Titel</span>
|
<span>Titel</span>
|
||||||
<span *ngIf="sortBy === 'title'" class="pl-3">
|
<span *ngIf="sortBy === 'title'" class="pl-3">
|
||||||
<span *ngIf="sortDescending">▲</span>
|
<span *ngIf="sortDescending">▲</span>
|
||||||
<span *ngIf="sortDescending === false">▼</span>
|
<span *ngIf="sortDescending === false">▼</span>
|
||||||
</span>
|
</span>
|
||||||
</th>
|
</th>
|
||||||
<th (click)="sortByContent()">
|
<th (click)="sortByContent()" class="sortable">
|
||||||
<span>Inhalt</span>
|
<span>Inhalt</span>
|
||||||
<span *ngIf="sortBy === 'content'" class="pl-3">
|
<span *ngIf="sortBy === 'content'" class="pl-3">
|
||||||
<span *ngIf="sortDescending">▲</span>
|
<span *ngIf="sortDescending">▲</span>
|
||||||
<span *ngIf="sortDescending === false">▼</span>
|
<span *ngIf="sortDescending === false">▼</span>
|
||||||
</span>
|
</span>
|
||||||
</th>
|
</th>
|
||||||
<th (click)="sortByTasks()">
|
<th (click)="sortByTasks()" class="sortable">
|
||||||
<span>Tasks</span>
|
<span>Userstory</span>
|
||||||
<span *ngIf="sortBy === 'tasks'" class="pl-3">
|
<span *ngIf="sortBy === 'userstory'" class="pl-3">
|
||||||
<span *ngIf="sortDescending">▲</span>
|
<span *ngIf="sortDescending">▲</span>
|
||||||
<span *ngIf="sortDescending === false">▼</span>
|
<span *ngIf="sortDescending === false">▼</span>
|
||||||
</span>
|
</span>
|
||||||
</th>
|
</th>
|
||||||
<th (click)="sortByPrio()">
|
<th (click)="sortByPrio()" class="sortable">
|
||||||
<span>Priorität</span>
|
<span>Priorität</span>
|
||||||
<span *ngIf="sortBy === 'priority'" class="pl-3">
|
<label class="pl-3" (click)="$event.stopPropagation()">
|
||||||
|
<select [(ngModel)]="filterPriority">
|
||||||
|
<option [ngValue]="null" selected></option>
|
||||||
|
<option *ngFor="let p of getAllPriorities()" [ngValue]="p">{{p}}</option>
|
||||||
|
</select>
|
||||||
|
</label>
|
||||||
|
<span *ngIf="sortBy === 'priority'" (click)="sortByPrio()" class="pl-3">
|
||||||
<span *ngIf="sortDescending">▲</span>
|
<span *ngIf="sortDescending">▲</span>
|
||||||
<span *ngIf="sortDescending === false">▼</span>
|
<span *ngIf="sortDescending === false">▼</span>
|
||||||
</span>
|
</span>
|
||||||
@ -56,7 +65,7 @@
|
|||||||
</thead>
|
</thead>
|
||||||
|
|
||||||
<tbody>
|
<tbody>
|
||||||
<tr *ngFor="let task of filteredItems">
|
<tr *ngFor="let task of filteredItems" [class.table-info]="task.id === highlightId">
|
||||||
<td>{{task.id}}</td>
|
<td>{{task.id}}</td>
|
||||||
<td>{{task.title}}</td>
|
<td>{{task.title}}</td>
|
||||||
<td>{{task.content}}</td>
|
<td>{{task.content}}</td>
|
||||||
|
@ -1,9 +1,10 @@
|
|||||||
import {Component} from '@angular/core';
|
import {Component} from '@angular/core';
|
||||||
import {BackendService, Priority, ScrumTask, ScrumUserstory} from '../services/backend.service';
|
import {BackendService, ScrumTask} from '../services/backend.service';
|
||||||
import {NgbModal} from '@ng-bootstrap/ng-bootstrap';
|
import {NgbModal} from '@ng-bootstrap/ng-bootstrap';
|
||||||
import {TaskFormComponent} from '../task-form/task-form.component';
|
import {TaskFormComponent} from '../task-form/task-form.component';
|
||||||
import {TableComponentBase} from '../services/table-component.base';
|
import {TableComponentBase} from '../services/table-component.base';
|
||||||
import {ActivatedRoute, Router} from '@angular/router';
|
import {ActivatedRoute, ParamMap, Router} from '@angular/router';
|
||||||
|
import {getNumberForPriority} from '../services/sorting.service';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-userstory-table',
|
selector: 'app-userstory-table',
|
||||||
@ -12,11 +13,14 @@ import {ActivatedRoute, Router} from '@angular/router';
|
|||||||
})
|
})
|
||||||
export class TaskTableComponent extends TableComponentBase<ScrumTask> {
|
export class TaskTableComponent extends TableComponentBase<ScrumTask> {
|
||||||
public filterUserstoryId: number | null = null;
|
public filterUserstoryId: number | null = null;
|
||||||
|
public filterPriority: string | null = null;
|
||||||
|
public highlightId: number;
|
||||||
|
|
||||||
public get filteredItems() {
|
public get filteredItems() {
|
||||||
if (this.filterUserstoryId === null || isNaN(this.filterUserstoryId)) {
|
return this.items.filter(task =>
|
||||||
return this.items;
|
(this.filterUserstoryId === null || task.userstoryid === this.filterUserstoryId)
|
||||||
}
|
&& (this.filterPriority === null || task.priority === this.filterPriority)
|
||||||
return this.items.filter(task => task.userstoryid === this.filterUserstoryId);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
@ -25,14 +29,8 @@ export class TaskTableComponent extends TableComponentBase<ScrumTask> {
|
|||||||
) {
|
) {
|
||||||
super();
|
super();
|
||||||
|
|
||||||
const params = route.snapshot.paramMap;
|
this.applyFilterParameters(route.snapshot.paramMap);
|
||||||
if (params.has('userstoryId')) {
|
route.paramMap.subscribe(map => this.applyFilterParameters(map));
|
||||||
this.filterUserstoryId = parseInt(params.get('userstoryId'));
|
|
||||||
}
|
|
||||||
if (params.has('id')) {
|
|
||||||
const id = parseInt(params.get('id'));
|
|
||||||
this.openTaskForm(this.items.find(t => t.id === id));
|
|
||||||
}
|
|
||||||
|
|
||||||
backendService.getTasks().subscribe(response => {
|
backendService.getTasks().subscribe(response => {
|
||||||
if (response.status > 399) {
|
if (response.status > 399) {
|
||||||
@ -43,6 +41,17 @@ export class TaskTableComponent extends TableComponentBase<ScrumTask> {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private applyFilterParameters(params: ParamMap) {
|
||||||
|
if (params.has('userstoryId')) {
|
||||||
|
this.filterUserstoryId = parseInt(params.get('userstoryId'));
|
||||||
|
} else {
|
||||||
|
this.filterUserstoryId = null;
|
||||||
|
}
|
||||||
|
if (params.has('id')) {
|
||||||
|
this.highlightId = parseInt(params.get('id'));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public deleteTask(task: ScrumTask) {
|
public deleteTask(task: ScrumTask) {
|
||||||
this.backendService.deleteTask(task).subscribe(response => {
|
this.backendService.deleteTask(task).subscribe(response => {
|
||||||
if (response.status > 399) {
|
if (response.status > 399) {
|
||||||
@ -69,37 +78,26 @@ export class TaskTableComponent extends TableComponentBase<ScrumTask> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
sortById() {
|
sortById() {
|
||||||
this.doNumericSort('id', us => us.id);
|
this.doNumericSort('id', task => task.id);
|
||||||
}
|
}
|
||||||
|
|
||||||
sortByTitle() {
|
sortByTitle() {
|
||||||
this.doStringSort('title', us => us.title);
|
this.doStringSort('title', task => task.title);
|
||||||
}
|
}
|
||||||
|
|
||||||
sortByContent() {
|
sortByContent() {
|
||||||
this.doStringSort('content', us => us.content);
|
this.doStringSort('content', task => task.content);
|
||||||
}
|
|
||||||
|
|
||||||
private getNumberForPriority(priority: Priority): number {
|
|
||||||
switch (priority) {
|
|
||||||
case Priority.High:
|
|
||||||
return 2;
|
|
||||||
case Priority.Medium:
|
|
||||||
return 1;
|
|
||||||
case Priority.Low:
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
sortByPrio() {
|
sortByPrio() {
|
||||||
this.doNumericSort('priority', us => this.getNumberForPriority(us.priority));
|
this.doNumericSort('priority', task => getNumberForPriority(task.priority));
|
||||||
}
|
|
||||||
|
|
||||||
getNumberOfTasks(userstory: ScrumUserstory) {
|
|
||||||
return this.items.filter(t => t.userstoryid === userstory.id).length;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
sortByTasks() {
|
sortByTasks() {
|
||||||
this.doNumericSort('tasks', us => this.getNumberOfTasks(us));
|
this.doNumericSort('userstory', task => task.userstoryid);
|
||||||
|
}
|
||||||
|
|
||||||
|
private findTaskById(id: number): ScrumTask {
|
||||||
|
return this.items.find(t => t.id === id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,3 +2,6 @@ table {
|
|||||||
table-layout: fixed;
|
table-layout: fixed;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
th.sortable:hover {
|
||||||
|
text-decoration: underline;
|
||||||
|
}
|
||||||
|
@ -8,36 +8,42 @@
|
|||||||
|
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
<th (click)="sortById()">
|
<th (click)="sortById()" class="sortable">
|
||||||
<span>ID</span>
|
<span>ID</span>
|
||||||
<span *ngIf="sortBy === 'id'" class="pl-3">
|
<span *ngIf="sortBy === 'id'" class="pl-3">
|
||||||
<span *ngIf="sortDescending">▲</span>
|
<span *ngIf="sortDescending">▲</span>
|
||||||
<span *ngIf="sortDescending === false">▼</span>
|
<span *ngIf="sortDescending === false">▼</span>
|
||||||
</span>
|
</span>
|
||||||
</th>
|
</th>
|
||||||
<th (click)="sortByTitle()">
|
<th (click)="sortByTitle()" class="sortable">
|
||||||
<span>Titel</span>
|
<span>Titel</span>
|
||||||
<span *ngIf="sortBy === 'title'" class="pl-3">
|
<span *ngIf="sortBy === 'title'" class="pl-3">
|
||||||
<span *ngIf="sortDescending">▲</span>
|
<span *ngIf="sortDescending">▲</span>
|
||||||
<span *ngIf="sortDescending === false">▼</span>
|
<span *ngIf="sortDescending === false">▼</span>
|
||||||
</span>
|
</span>
|
||||||
</th>
|
</th>
|
||||||
<th (click)="sortByContent()">
|
<th (click)="sortByContent()" class="sortable">
|
||||||
<span>Inhalt</span>
|
<span>Inhalt</span>
|
||||||
<span *ngIf="sortBy === 'content'" class="pl-3">
|
<span *ngIf="sortBy === 'content'" class="pl-3">
|
||||||
<span *ngIf="sortDescending">▲</span>
|
<span *ngIf="sortDescending">▲</span>
|
||||||
<span *ngIf="sortDescending === false">▼</span>
|
<span *ngIf="sortDescending === false">▼</span>
|
||||||
</span>
|
</span>
|
||||||
</th>
|
</th>
|
||||||
<th (click)="sortByTasks()">
|
<th (click)="sortByTasks()" class="sortable">
|
||||||
<span>Tasks</span>
|
<span>Tasks</span>
|
||||||
<span *ngIf="sortBy === 'tasks'" class="pl-3">
|
<span *ngIf="sortBy === 'tasks'" class="pl-3">
|
||||||
<span *ngIf="sortDescending">▲</span>
|
<span *ngIf="sortDescending">▲</span>
|
||||||
<span *ngIf="sortDescending === false">▼</span>
|
<span *ngIf="sortDescending === false">▼</span>
|
||||||
</span>
|
</span>
|
||||||
</th>
|
</th>
|
||||||
<th (click)="sortByPrio()">
|
<th (click)="sortByPrio()" class="sortable">
|
||||||
<span>Priorität</span>
|
<span>Priorität</span>
|
||||||
|
<label class="pl-3" (click)="$event.stopPropagation()">
|
||||||
|
<select [(ngModel)]="filterPriority">
|
||||||
|
<option [ngValue]="null" selected></option>
|
||||||
|
<option *ngFor="let p of getAllPriorities()" [ngValue]="p">{{p}}</option>
|
||||||
|
</select>
|
||||||
|
</label>
|
||||||
<span *ngIf="sortBy === 'priority'" class="pl-3">
|
<span *ngIf="sortBy === 'priority'" class="pl-3">
|
||||||
<span *ngIf="sortDescending">▲</span>
|
<span *ngIf="sortDescending">▲</span>
|
||||||
<span *ngIf="sortDescending === false">▼</span>
|
<span *ngIf="sortDescending === false">▼</span>
|
||||||
@ -48,7 +54,7 @@
|
|||||||
</thead>
|
</thead>
|
||||||
|
|
||||||
<tbody>
|
<tbody>
|
||||||
<tr *ngFor="let userstory of items">
|
<tr *ngFor="let userstory of filteredItems" [class.table-info]="userstory.id === highlightId">
|
||||||
<td>{{userstory.id}}</td>
|
<td>{{userstory.id}}</td>
|
||||||
<td>{{userstory.title}}</td>
|
<td>{{userstory.title}}</td>
|
||||||
<td>{{userstory.content}}</td>
|
<td>{{userstory.content}}</td>
|
||||||
|
@ -4,7 +4,7 @@ import {NgbModal} from '@ng-bootstrap/ng-bootstrap';
|
|||||||
import {TableComponentBase} from '../services/table-component.base';
|
import {TableComponentBase} from '../services/table-component.base';
|
||||||
import {getNumberForPriority} from '../services/sorting.service';
|
import {getNumberForPriority} from '../services/sorting.service';
|
||||||
import {UserstoryFormComponent} from '../userstory-form/userstory-form.component';
|
import {UserstoryFormComponent} from '../userstory-form/userstory-form.component';
|
||||||
import {ActivatedRoute, Router} from '@angular/router';
|
import {ActivatedRoute, ParamMap, Router} from '@angular/router';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-userstory-table',
|
selector: 'app-userstory-table',
|
||||||
@ -13,6 +13,12 @@ import {ActivatedRoute, Router} from '@angular/router';
|
|||||||
})
|
})
|
||||||
export class UserstoryTableComponent extends TableComponentBase<ScrumUserstory> {
|
export class UserstoryTableComponent extends TableComponentBase<ScrumUserstory> {
|
||||||
public tasks: ScrumTask[] = [];
|
public tasks: ScrumTask[] = [];
|
||||||
|
public filterPriority: string | null = null;
|
||||||
|
public highlightId: number;
|
||||||
|
|
||||||
|
public get filteredItems() {
|
||||||
|
return this.items.filter(task => this.filterPriority === null || task.priority === this.filterPriority);
|
||||||
|
}
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
private backendService: BackendService, private modalService: NgbModal,
|
private backendService: BackendService, private modalService: NgbModal,
|
||||||
@ -20,19 +26,14 @@ export class UserstoryTableComponent extends TableComponentBase<ScrumUserstory>
|
|||||||
) {
|
) {
|
||||||
super();
|
super();
|
||||||
|
|
||||||
const params = route.snapshot.paramMap;
|
this.applyFilterParameters(this.route.snapshot.paramMap);
|
||||||
|
this.route.paramMap.subscribe(map => this.applyFilterParameters(map));
|
||||||
|
|
||||||
backendService.getUserstories().subscribe(response => {
|
backendService.getUserstories().subscribe(response => {
|
||||||
if (response.status > 399) {
|
if (response.status > 399) {
|
||||||
alert('Fehler');
|
alert('Fehler');
|
||||||
} else {
|
} else {
|
||||||
this.items.push(...response.body);
|
this.items.push(...response.body);
|
||||||
|
|
||||||
// Wenn /userstories;id=3 aufgerufen wird, öffne die Userstory mit ID 3
|
|
||||||
const userstory = this.findUserstoryById(parseInt(params.get('id')));
|
|
||||||
if (userstory !== null) {
|
|
||||||
this.openUserstoryForm(userstory);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
backendService.getTasks().subscribe(response => {
|
backendService.getTasks().subscribe(response => {
|
||||||
@ -44,12 +45,10 @@ export class UserstoryTableComponent extends TableComponentBase<ScrumUserstory>
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private findUserstoryById(id: number): ScrumUserstory {
|
private applyFilterParameters(params: ParamMap) {
|
||||||
const userstoriesWithId = this.items.filter(us => us.id === id);
|
if (params.has('id')) {
|
||||||
if (userstoriesWithId.length === 0) {
|
this.highlightId = parseInt(params.get('id'));
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
return userstoriesWithId[0];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public deleteUserstory(userstory: ScrumUserstory) {
|
public deleteUserstory(userstory: ScrumUserstory) {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user