* tsp board disabled

* multi assignee
This commit is contained in:
Dávid Danyi 2017-11-13 13:54:39 +01:00
parent cc8a3ddd03
commit 82184678b9
6 changed files with 161 additions and 91 deletions

View File

@ -3,25 +3,25 @@ import {Subscription} from "rxjs/Subscription";
import {TimerObservable} from "rxjs/observable/TimerObservable";
import {KanbanService} from "./kanban/shared/kanban.service";
import {ActivatedRoute, NavigationEnd, Router} from "@angular/router";
// import {ActivatedRoute, NavigationEnd, Router} from "@angular/router";
import {SelfUpdaterService} from "./kanban/shared/self-updater.service";
import {TspInfoService} from "./tsp-info/shared/tsp-info.service";
// import {TspInfoService} from "./tsp-info/shared/tsp-info.service";
const TIMER_DEPLOY_REFRESH = 30000;
const TIMER_JIRA_REFRESH = 60000;
const TIMER_TSPINFO_REFRESH = 60000;
const TIMER_PAGE_SWITCH_TICK = 1000;
// const TIMER_TSPINFO_REFRESH = 60000;
// const TIMER_PAGE_SWITCH_TICK = 1000;
/**
* Page switch timer in seconds
* @type {number}
*/
const TIMESPENT_KANBAN = 120000;
const TIMESPENT_TSPINFO = 30000;
// const TIMESPENT_KANBAN = 120000;
// const TIMESPENT_TSPINFO = 30000;
const PAGE_KANBAN = '/kanban';
const PAGE_TSPINFO = '/tspinfopage';
// const PAGE_KANBAN = '/kanban';
// const PAGE_TSPINFO = '/tspinfopage';
@Component({
selector: 'app-root',
@ -29,21 +29,21 @@ const PAGE_TSPINFO = '/tspinfopage';
styleUrls: ['./app.component.css']
})
export class AppComponent implements OnInit, OnDestroy {
private currentPage: string = PAGE_KANBAN;
private lastNavOccured: number = Date.now();
private autoSwitchEnabled: boolean = true;
// private currentPage: string = PAGE_KANBAN;
// private lastNavOccured: number = Date.now();
// private autoSwitchEnabled: boolean = true;
private selfUpdateCheckerTimer: Subscription;
private reloadKanbanTimer: Subscription;
private reloadTspInfoTimer: Subscription;
private pageSwitchTimer: Subscription;
// private reloadTspInfoTimer: Subscription;
// private pageSwitchTimer: Subscription;
constructor(private selfUpdaterService: SelfUpdaterService,
private kanbanService: KanbanService,
private tspInfoService: TspInfoService,
private router: Router,
private activatedRoute: ActivatedRoute) {
}
// private tspInfoService: TspInfoService,
// private router: Router,
// private activatedRoute: ActivatedRoute
) {}
/**
* Initialize application timers:
@ -60,81 +60,81 @@ export class AppComponent implements OnInit, OnDestroy {
this.reloadKanbanTimer = timer1.subscribe(() => {
this.kanbanService.reload();
});
let timer2 = TimerObservable.create(TIMER_TSPINFO_REFRESH, TIMER_TSPINFO_REFRESH);
this.reloadTspInfoTimer = timer2.subscribe(() => {
this.tspInfoService.reload();
});
// let timer2 = TimerObservable.create(TIMER_TSPINFO_REFRESH, TIMER_TSPINFO_REFRESH);
// this.reloadTspInfoTimer = timer2.subscribe(() => {
// this.tspInfoService.reload();
// });
this.router.events
.filter(e => e instanceof NavigationEnd)
.map(() => {
let route = this.activatedRoute;
while (route.firstChild) {
route = route.firstChild;
}
return route;
})
.filter((route) => route.outlet === 'primary')
.mergeMap((route) => route.data)
.subscribe(data => {
if (!data['disableAutoSwitch']) {
let timer4 = TimerObservable.create(TIMER_PAGE_SWITCH_TICK, TIMER_PAGE_SWITCH_TICK);
this.pageSwitchTimer = timer4.subscribe(this.switchSubscriber.bind(this));
}
});
// this.router.events
// .filter(e => e instanceof NavigationEnd)
// .map(() => {
// let route = this.activatedRoute;
// while (route.firstChild) {
// route = route.firstChild;
// }
// return route;
// })
// .filter((route) => route.outlet === 'primary')
// .mergeMap((route) => route.data)
// .subscribe(data => {
// if (!data['disableAutoSwitch']) {
// let timer4 = TimerObservable.create(TIMER_PAGE_SWITCH_TICK, TIMER_PAGE_SWITCH_TICK);
// this.pageSwitchTimer = timer4.subscribe(this.switchSubscriber.bind(this));
// }
// });
}
public ngOnDestroy() {
this.selfUpdateCheckerTimer.unsubscribe();
this.reloadKanbanTimer.unsubscribe();
this.reloadTspInfoTimer.unsubscribe();
if (this.pageSwitchTimer) {
this.pageSwitchTimer.unsubscribe();
}
// this.reloadTspInfoTimer.unsubscribe();
// if (this.pageSwitchTimer) {
// this.pageSwitchTimer.unsubscribe();
// }
}
private switchSubscriber() {
let now = new Date();
let weekDay = now.getDay();
// on weekdays
if (weekDay > 0 && weekDay < 6) {
if (now.getHours() == 10) {
if (this.autoSwitchEnabled && now.getMinutes() > 14) {
this.navigateToPage(PAGE_KANBAN);
this.autoSwitchEnabled = false;
}
if (!this.autoSwitchEnabled && now.getMinutes() > 30) {
this.autoSwitchEnabled = true;
}
}
}
if (this.autoSwitchEnabled) {
let compareTimer: number = 0;
let switchTo: string = '';
switch (this.currentPage) {
case PAGE_KANBAN:
compareTimer = TIMESPENT_KANBAN;
switchTo = PAGE_TSPINFO;
break;
case PAGE_TSPINFO:
compareTimer = TIMESPENT_TSPINFO;
switchTo = PAGE_KANBAN;
break;
default:
console.error("Unknown page in pageSwitcherTimer");
return false;
}
if ((Date.now() - this.lastNavOccured) > compareTimer) {
this.navigateToPage(switchTo);
}
}
}
private navigateToPage(page: string) {
if (page != this.currentPage) {
this.router.navigate([page]);
this.currentPage = page;
this.lastNavOccured = Date.now();
}
}
// private switchSubscriber() {
// let now = new Date();
// let weekDay = now.getDay();
// // on weekdays
// if (weekDay > 0 && weekDay < 6) {
// if (now.getHours() == 10) {
// if (this.autoSwitchEnabled && now.getMinutes() > 14) {
// this.navigateToPage(PAGE_KANBAN);
// this.autoSwitchEnabled = false;
// }
// if (!this.autoSwitchEnabled && now.getMinutes() > 30) {
// this.autoSwitchEnabled = true;
// }
// }
// }
// if (this.autoSwitchEnabled) {
// let compareTimer: number = 0;
// let switchTo: string = '';
// switch (this.currentPage) {
// case PAGE_KANBAN:
// compareTimer = TIMESPENT_KANBAN;
// switchTo = PAGE_TSPINFO;
// break;
// case PAGE_TSPINFO:
// compareTimer = TIMESPENT_TSPINFO;
// switchTo = PAGE_KANBAN;
// break;
// default:
// console.error("Unknown page in pageSwitcherTimer");
// return false;
// }
// if ((Date.now() - this.lastNavOccured) > compareTimer) {
// this.navigateToPage(switchTo);
// }
// }
// }
//
// private navigateToPage(page: string) {
// if (page != this.currentPage) {
// this.router.navigate([page]);
// this.currentPage = page;
// this.lastNavOccured = Date.now();
// }
// }
}

View File

@ -57,3 +57,43 @@ a:hover {
/*.ui.divided.items > .item.trivial.bottom-separator {*/
/*border-bottom: 1px solid rgba(181, 204, 24, 0.5);*/
/*}*/
.ui.images {
width: 45px;
height: 45px;
margin-left: 0px;
margin-right: 4px;
margin-bottom: 0;
border-radius: 4px;
overflow: hidden;
}
.ui.images .image {
margin: 0;
width: 45px;
height: 45px;
}
/* 2 images */
.ui.two.images .image {
width: 22px;
object-fit: cover;
}
/* 3 images */
.ui.three.images .image {
height: 22px;
}
.ui.three.images .image:first-child {
object-fit: cover;
}
.ui.three.images .image:not(:first-child) {
width: 22px;
margin-top: -14px;
}
/* 4 images */
.ui.four.images .image {
height: 22px;
width: 22px;
}

View File

@ -5,17 +5,27 @@
</ng-template>
</h1>
<div class="ui divided items">
<div class="item {{kanbanEntry.issuePriority|lowercase}}" [ngClass]="entryClass(kanbanEntry)" *ngFor="let kanbanEntry of kanbanEntries">
<div *ngFor="let kanbanEntry of kanbanEntries"
class="item {{kanbanEntry.issuePriority|lowercase}}"
[ngClass]="entryClass(kanbanEntry)">
<div class="content">
<div class="task-description">
<ng-template [ngIf]="hasLabels(kanbanEntry)">
<span *ngFor="let label of kanbanEntry.labels" class="ui mini {{labelClass(label)}} right floated label">{{label|uppercase|blockedDays:kanbanEntry.daysBlocked}}</span>
<span *ngFor="let label of kanbanEntry.labels"
class="ui mini {{labelClass(label)}} right floated label">{{label|uppercase|blockedDays:kanbanEntry.daysBlocked}}</span>
</ng-template>
<span *ngIf="wasBlocked(kanbanEntry)" class="ui mini {{labelClass('blocked')}} right floated label">{{kanbanEntry.daysBlocked}}D</span>
<div class="ui jira-avatar floated image">
<div *ngIf="!hasMultiAssignee(kanbanEntry)" class="ui jira-avatar floated image">
<img src="{{avatarUrl(kanbanEntry.assignee?.avatar)}}" [title]="kanbanEntry.assignee?.name">
</div>
<a [href]="jiraHref(kanbanEntry)" target="_blank" [innerHTML]="kanbanEntry.summary|shortenText|priorityColor:kanbanEntry.issuePriorityIcon:kanbanEntry.worklog" [title]="kanbanEntry.summary"></a>
<div *ngIf="hasMultiAssignee(kanbanEntry)" class="ui jira-avatar floated {{assigneeCount(kanbanEntry)}} images">
<img *ngFor="let assignee of getAssignees(kanbanEntry)" class="image"
src="{{avatarUrl(assignee?.avatar)}}"
[title]="assignee?.name">
</div>
<a [href]="jiraHref(kanbanEntry)" target="_blank"
[innerHTML]="kanbanEntry.summary|shortenText|priorityColor:kanbanEntry.issuePriorityIcon:kanbanEntry.worklog"
[title]="kanbanEntry.summary"></a>
</div>
</div>
</div>

View File

@ -2,6 +2,7 @@ import {Component, Input} from '@angular/core';
import {environment} from "../../../environments/environment";
import {KanbanEntry} from "../shared";
import { JiraAssignee } from "../shared/jira-assignee.model";
const DEFAULT_AVATAR = '/assets/riddler.png';
const JIRA_BOARD_BASE_HREF = 'https://jirapducc.mo.ca.am.ericsson.se/browse/';
@ -97,4 +98,22 @@ export class KanbanEntryItemComponent {
return kanbanEntry.daysBlocked > 0
&& kanbanEntry.labels.every(label => label.toUpperCase() != 'BLOCKED');
}
public hasMultiAssignee(kanbanEntry: KanbanEntry): boolean {
return kanbanEntry.additionalAssignees.length > 0;
}
public assigneeCount(kanbanEntry: KanbanEntry): string {
let count = 1 + kanbanEntry.additionalAssignees.length;
switch (count) {
case 2: return "two";
case 3: return "three";
case 4:
default: return "four";
}
}
public getAssignees(kanbanEntry: KanbanEntry): Array<JiraAssignee> {
return [].concat([kanbanEntry.assignee], kanbanEntry.additionalAssignees);
}
}

View File

@ -9,6 +9,7 @@ export class KanbanEntry {
public issueType: JiraIssueType;
public status: JiraStatus;
public assignee: JiraAssignee;
public additionalAssignees: Array<JiraAssignee> = [];
public issuePriority: string;
public issuePriorityIcon: string;
public labels: Array<string>;

View File

@ -5,5 +5,5 @@
export const environment = {
production: false,
apiUri: "http://localhost:8080",
apiUri: "http://localhost:8888",
};