diff --git a/package-lock.json b/package-lock.json index 7f50e89..70e63e8 100644 --- a/package-lock.json +++ b/package-lock.json @@ -567,6 +567,14 @@ "semver-intersect": "^1.1.2" } }, + "@types/date-fns": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/@types/date-fns/-/date-fns-2.6.0.tgz", + "integrity": "sha1-sGLKRlYgApCb4MY6ZGftFzE2rME=", + "requires": { + "date-fns": "*" + } + }, "@types/jasmine": { "version": "2.8.6", "resolved": "https://registry.npmjs.org/@types/jasmine/-/jasmine-2.8.6.tgz", @@ -2452,9 +2460,9 @@ } }, "date-fns": { - "version": "2.0.0-alpha.1", - "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-2.0.0-alpha.1.tgz", - "integrity": "sha512-4gYdF1rDgv9X/0ko69pt+FgpQtDU5rgqZVmckIOhDicfCSTndwHMhUhLJw+pa4DlPdzIkEBtHg6L6VlQ6ueD1g==" + "version": "1.29.0", + "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-1.29.0.tgz", + "integrity": "sha512-lbTXWZ6M20cWH8N9S6afb0SBm6tMk+uUg6z3MqHPKE9atmsY3kJkTm8vKe93izJ2B2+q5MV990sM2CHgtAZaOw==" }, "date-now": { "version": "0.1.4", @@ -6661,6 +6669,11 @@ "rxjs": "^5.0.1" }, "dependencies": { + "date-fns": { + "version": "2.0.0-alpha.1", + "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-2.0.0-alpha.1.tgz", + "integrity": "sha512-4gYdF1rDgv9X/0ko69pt+FgpQtDU5rgqZVmckIOhDicfCSTndwHMhUhLJw+pa4DlPdzIkEBtHg6L6VlQ6ueD1g==" + }, "rxjs": { "version": "5.5.7", "resolved": "http://registry.npmjs.org/rxjs/-/rxjs-5.5.7.tgz", diff --git a/package.json b/package.json index 4edcde5..8ed345a 100644 --- a/package.json +++ b/package.json @@ -20,8 +20,10 @@ "@angular/platform-browser": "^6.1.0", "@angular/platform-browser-dynamic": "^6.1.0", "@angular/router": "^6.1.0", + "@types/date-fns": "^2.6.0", "@types/marked": "^0.4.1", "core-js": "^2.5.4", + "date-fns": "^1.29.0", "marked": "^0.5.0", "ng2-semantic-ui": "^0.9.7", "rxjs": "^6.0.0", diff --git a/src/app/admin/team-editor/team-editor.component.html b/src/app/admin/team-editor/team-editor.component.html index e32b7c6..43e4ad5 100755 --- a/src/app/admin/team-editor/team-editor.component.html +++ b/src/app/admin/team-editor/team-editor.component.html @@ -1,6 +1,6 @@

Team editor

-
+
@@ -22,7 +22,37 @@
-

Column configuration

+

Kanban configuration

+

Daily standup timer

+
+
+
+ + +
+
+
+ +
+ + +
+
+
+ +
+ + +
+
+
+ +

Columns

@@ -119,7 +149,7 @@ (click)="removeLabel(label)">
-

Team members

+

Team members

Back to teams list diff --git a/src/app/admin/team-editor/team-editor.component.ts b/src/app/admin/team-editor/team-editor.component.ts index 5c80ea6..c90cde4 100755 --- a/src/app/admin/team-editor/team-editor.component.ts +++ b/src/app/admin/team-editor/team-editor.component.ts @@ -6,7 +6,7 @@ import { TeamService } from '../../shared/service/team.service'; import { Team } from '../../shared/team'; import { Member } from '../../shared/member'; import { Label } from '../../shared/label'; -import {NgModel} from '@angular/forms'; +import {NgForm, NgModel} from '@angular/forms'; @Component({ selector: 'app-team-editor', @@ -116,15 +116,15 @@ export class TeamEditorComponent implements OnInit { } } - get canSave(): boolean { - return [ + public canSave(form: NgForm): boolean { + return form.valid && [ this.team.name.trim(), this.team.members ].every(field => field.length > 0) && this.team.filterId > 0; } - public saveTeam() { - if (this.canSave) { + public saveTeam(form: NgForm) { + if (this.canSave(form)) { this.teamService.persist(this.team).subscribe( () => this.router.navigate(['/admin/teams']) ); diff --git a/src/app/display/kanban-board/kanban-board.component.ts b/src/app/display/kanban-board/kanban-board.component.ts index 83840ce..f86ada3 100755 --- a/src/app/display/kanban-board/kanban-board.component.ts +++ b/src/app/display/kanban-board/kanban-board.component.ts @@ -27,7 +27,7 @@ export class KanbanBoardComponent implements OnInit { * Set page title, and handle preloaded kanbanBoard data */ ngOnInit() { - this.titleService.setTitle('TaurusXFT : Kanban board'); + this.titleService.setTitle(`${this.settingService.team.name} : Kanban board`); this.route.data.subscribe((data: { kanbanBoard: KanbanBoard, }) => { diff --git a/src/app/shared/service/timer.service.ts b/src/app/shared/service/timer.service.ts index 641fe07..accd832 100755 --- a/src/app/shared/service/timer.service.ts +++ b/src/app/shared/service/timer.service.ts @@ -5,8 +5,12 @@ import { Subject, timer, Subscription } from 'rxjs'; import { ActivationStart, Router } from '@angular/router'; import { SlideShowService } from '../../display/slide-show.service'; import { filter, switchMap } from 'rxjs/operators'; +import * as isWithinRange from 'date-fns/is_within_range'; +import * as min from 'date-fns/min'; +import * as max from 'date-fns/max'; const TIMER_UPDATE_POLL_INTERVAL = 30000; +const TIME_SEPARATOR = ':'; @Injectable() export class TimerService implements OnDestroy { @@ -48,7 +52,10 @@ export class TimerService implements OnDestroy { } private changeSlide() { - if (this.autoSwitch) { + if (this.autoSwitch && this.isDuringDailyStandup()) { + this.router.navigate(['/kanban']); + } + if (this.autoSwitch && !this.isDuringDailyStandup()) { this.slideShowService.nextSlide(); } this.setSlideTimer(this.settings.slideInterval); @@ -57,4 +64,20 @@ export class TimerService implements OnDestroy { public setSlideTimer(delay: number) { this.slideTimerSubject.next(delay); } + + private isDuringDailyStandup(): boolean { + if (this.settings.team.dailyLockEnabled) { + const now = new Date(); + const startsParts = this.settings.team.dailyStartTime.split(TIME_SEPARATOR).map(part => +part); + const endsParts = this.settings.team.dailyEndTime.split(TIME_SEPARATOR).map(part => +part); + const times = [ + new Date(now.getFullYear(), now.getMonth(), now.getDay(), startsParts[0], startsParts[1]), + new Date(now.getFullYear(), now.getMonth(), now.getDay(), endsParts[0], endsParts[1]) + ]; + const startsAt = min(...times); + const endsAt = max(...times); + return isWithinRange(now, startsAt, endsAt); + } + return false; + } } diff --git a/src/app/shared/team.ts b/src/app/shared/team.ts index 8ac9392..c85fe65 100755 --- a/src/app/shared/team.ts +++ b/src/app/shared/team.ts @@ -7,6 +7,9 @@ export class Team { name: String = ''; members: Array = []; filterId = 0; + dailyLockEnabled: false; + dailyStartTime: string; + dailyEndTime: string; backlogColumn: KanbanColumn = new KanbanColumn(); inprogressColumn: KanbanColumn = new KanbanColumn(); verificationColumn: KanbanColumn = new KanbanColumn();