* daily kanban slide lock added
This commit is contained in:
parent
aa995e845a
commit
57f85768eb
19
package-lock.json
generated
19
package-lock.json
generated
@ -567,6 +567,14 @@
|
|||||||
"semver-intersect": "^1.1.2"
|
"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": {
|
"@types/jasmine": {
|
||||||
"version": "2.8.6",
|
"version": "2.8.6",
|
||||||
"resolved": "https://registry.npmjs.org/@types/jasmine/-/jasmine-2.8.6.tgz",
|
"resolved": "https://registry.npmjs.org/@types/jasmine/-/jasmine-2.8.6.tgz",
|
||||||
@ -2452,9 +2460,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"date-fns": {
|
"date-fns": {
|
||||||
"version": "2.0.0-alpha.1",
|
"version": "1.29.0",
|
||||||
"resolved": "https://registry.npmjs.org/date-fns/-/date-fns-2.0.0-alpha.1.tgz",
|
"resolved": "https://registry.npmjs.org/date-fns/-/date-fns-1.29.0.tgz",
|
||||||
"integrity": "sha512-4gYdF1rDgv9X/0ko69pt+FgpQtDU5rgqZVmckIOhDicfCSTndwHMhUhLJw+pa4DlPdzIkEBtHg6L6VlQ6ueD1g=="
|
"integrity": "sha512-lbTXWZ6M20cWH8N9S6afb0SBm6tMk+uUg6z3MqHPKE9atmsY3kJkTm8vKe93izJ2B2+q5MV990sM2CHgtAZaOw=="
|
||||||
},
|
},
|
||||||
"date-now": {
|
"date-now": {
|
||||||
"version": "0.1.4",
|
"version": "0.1.4",
|
||||||
@ -6661,6 +6669,11 @@
|
|||||||
"rxjs": "^5.0.1"
|
"rxjs": "^5.0.1"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"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": {
|
"rxjs": {
|
||||||
"version": "5.5.7",
|
"version": "5.5.7",
|
||||||
"resolved": "http://registry.npmjs.org/rxjs/-/rxjs-5.5.7.tgz",
|
"resolved": "http://registry.npmjs.org/rxjs/-/rxjs-5.5.7.tgz",
|
||||||
|
|||||||
@ -20,8 +20,10 @@
|
|||||||
"@angular/platform-browser": "^6.1.0",
|
"@angular/platform-browser": "^6.1.0",
|
||||||
"@angular/platform-browser-dynamic": "^6.1.0",
|
"@angular/platform-browser-dynamic": "^6.1.0",
|
||||||
"@angular/router": "^6.1.0",
|
"@angular/router": "^6.1.0",
|
||||||
|
"@types/date-fns": "^2.6.0",
|
||||||
"@types/marked": "^0.4.1",
|
"@types/marked": "^0.4.1",
|
||||||
"core-js": "^2.5.4",
|
"core-js": "^2.5.4",
|
||||||
|
"date-fns": "^1.29.0",
|
||||||
"marked": "^0.5.0",
|
"marked": "^0.5.0",
|
||||||
"ng2-semantic-ui": "^0.9.7",
|
"ng2-semantic-ui": "^0.9.7",
|
||||||
"rxjs": "^6.0.0",
|
"rxjs": "^6.0.0",
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
<div class="ui main container">
|
<div class="ui main container">
|
||||||
<h1 class="ui dividing header">Team editor</h1>
|
<h1 class="ui dividing header">Team editor</h1>
|
||||||
<form class="ui form" #teamEditorForm (ngSubmit)="saveTeam()">
|
<form class="ui form" #teamEditorForm (ngSubmit)="saveTeam(f)" #f="ngForm">
|
||||||
<div class="two fields">
|
<div class="two fields">
|
||||||
<div class="six wide field" [class.error]="checkError(teamName)">
|
<div class="six wide field" [class.error]="checkError(teamName)">
|
||||||
<label for="team_name">Team name</label>
|
<label for="team_name">Team name</label>
|
||||||
@ -22,7 +22,37 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<h4 class="ui dividing header">Column configuration</h4>
|
<h3 class="ui dividing header">Kanban configuration</h3>
|
||||||
|
<h4 class="ui dividing header">Daily standup timer</h4>
|
||||||
|
<div class="three inline fields">
|
||||||
|
<div class="two wide field">
|
||||||
|
<div class="ui checkbox">
|
||||||
|
<input type="checkbox" id="daily_lock_timer" name="daily_lock_timer"
|
||||||
|
[(ngModel)]="team.dailyLockEnabled">
|
||||||
|
<label for="daily_lock_timer">Enabled</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="four wide field" [class.error]="checkError(startTime)">
|
||||||
|
<label for="daily_start">Starts</label>
|
||||||
|
<div class="ui left icon input">
|
||||||
|
<input type="time" id="daily_start" name="daily_start"
|
||||||
|
min="9:00" max="15:00" [required]="team.dailyLockEnabled"
|
||||||
|
[(ngModel)]="team.dailyStartTime" #startTime="ngModel">
|
||||||
|
<i class="time icon"></i>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="four wide field" [class.error]="checkError(endTime)">
|
||||||
|
<label for="daily_end">Ends</label>
|
||||||
|
<div class="ui left icon input">
|
||||||
|
<input type="time" id="daily_end" name="daily_end"
|
||||||
|
min="9:00" max="15:00" [required]="team.dailyLockEnabled"
|
||||||
|
[(ngModel)]="team.dailyEndTime" #endTime="ngModel">
|
||||||
|
<i class="time icon"></i>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h4 class="ui dividing header">Columns</h4>
|
||||||
<div class="four fields">
|
<div class="four fields">
|
||||||
<div class="six wide field">
|
<div class="six wide field">
|
||||||
<label>Jira status</label>
|
<label>Jira status</label>
|
||||||
@ -119,7 +149,7 @@
|
|||||||
(click)="removeLabel(label)"></i></span>
|
(click)="removeLabel(label)"></i></span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<h4 class="ui dividing header">Team members</h4>
|
<h3 class="ui dividing header">Team members</h3>
|
||||||
<div class="three inline fields">
|
<div class="three inline fields">
|
||||||
<div class="two wide field">
|
<div class="two wide field">
|
||||||
<button type="button" class="ui fluid button"
|
<button type="button" class="ui fluid button"
|
||||||
@ -165,8 +195,8 @@
|
|||||||
</table>
|
</table>
|
||||||
|
|
||||||
<button type="submit" class="ui button"
|
<button type="submit" class="ui button"
|
||||||
[class.positive]="canSave"
|
[class.positive]="canSave(f)"
|
||||||
[class.disabled]="!canSave"><i class="save outline icon"></i>Save changes
|
[class.disabled]="!canSave(f)"><i class="save outline icon"></i>Save changes
|
||||||
</button>
|
</button>
|
||||||
<a class="ui button"
|
<a class="ui button"
|
||||||
[routerLink]="['/admin/teams']"><i class="left angle icon"></i>Back to teams list</a>
|
[routerLink]="['/admin/teams']"><i class="left angle icon"></i>Back to teams list</a>
|
||||||
|
|||||||
@ -6,7 +6,7 @@ import { TeamService } from '../../shared/service/team.service';
|
|||||||
import { Team } from '../../shared/team';
|
import { Team } from '../../shared/team';
|
||||||
import { Member } from '../../shared/member';
|
import { Member } from '../../shared/member';
|
||||||
import { Label } from '../../shared/label';
|
import { Label } from '../../shared/label';
|
||||||
import {NgModel} from '@angular/forms';
|
import {NgForm, NgModel} from '@angular/forms';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-team-editor',
|
selector: 'app-team-editor',
|
||||||
@ -116,15 +116,15 @@ export class TeamEditorComponent implements OnInit {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
get canSave(): boolean {
|
public canSave(form: NgForm): boolean {
|
||||||
return [
|
return form.valid && [
|
||||||
this.team.name.trim(),
|
this.team.name.trim(),
|
||||||
this.team.members
|
this.team.members
|
||||||
].every(field => field.length > 0) && this.team.filterId > 0;
|
].every(field => field.length > 0) && this.team.filterId > 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
public saveTeam() {
|
public saveTeam(form: NgForm) {
|
||||||
if (this.canSave) {
|
if (this.canSave(form)) {
|
||||||
this.teamService.persist(this.team).subscribe(
|
this.teamService.persist(this.team).subscribe(
|
||||||
() => this.router.navigate(['/admin/teams'])
|
() => this.router.navigate(['/admin/teams'])
|
||||||
);
|
);
|
||||||
|
|||||||
@ -27,7 +27,7 @@ export class KanbanBoardComponent implements OnInit {
|
|||||||
* Set page title, and handle preloaded kanbanBoard data
|
* Set page title, and handle preloaded kanbanBoard data
|
||||||
*/
|
*/
|
||||||
ngOnInit() {
|
ngOnInit() {
|
||||||
this.titleService.setTitle('TaurusXFT : Kanban board');
|
this.titleService.setTitle(`${this.settingService.team.name} : Kanban board`);
|
||||||
this.route.data.subscribe((data: {
|
this.route.data.subscribe((data: {
|
||||||
kanbanBoard: KanbanBoard,
|
kanbanBoard: KanbanBoard,
|
||||||
}) => {
|
}) => {
|
||||||
|
|||||||
@ -5,8 +5,12 @@ import { Subject, timer, Subscription } from 'rxjs';
|
|||||||
import { ActivationStart, Router } from '@angular/router';
|
import { ActivationStart, Router } from '@angular/router';
|
||||||
import { SlideShowService } from '../../display/slide-show.service';
|
import { SlideShowService } from '../../display/slide-show.service';
|
||||||
import { filter, switchMap } from 'rxjs/operators';
|
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 TIMER_UPDATE_POLL_INTERVAL = 30000;
|
||||||
|
const TIME_SEPARATOR = ':';
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class TimerService implements OnDestroy {
|
export class TimerService implements OnDestroy {
|
||||||
@ -48,7 +52,10 @@ export class TimerService implements OnDestroy {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private changeSlide() {
|
private changeSlide() {
|
||||||
if (this.autoSwitch) {
|
if (this.autoSwitch && this.isDuringDailyStandup()) {
|
||||||
|
this.router.navigate(['/kanban']);
|
||||||
|
}
|
||||||
|
if (this.autoSwitch && !this.isDuringDailyStandup()) {
|
||||||
this.slideShowService.nextSlide();
|
this.slideShowService.nextSlide();
|
||||||
}
|
}
|
||||||
this.setSlideTimer(this.settings.slideInterval);
|
this.setSlideTimer(this.settings.slideInterval);
|
||||||
@ -57,4 +64,20 @@ export class TimerService implements OnDestroy {
|
|||||||
public setSlideTimer(delay: number) {
|
public setSlideTimer(delay: number) {
|
||||||
this.slideTimerSubject.next(delay);
|
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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -7,6 +7,9 @@ export class Team {
|
|||||||
name: String = '';
|
name: String = '';
|
||||||
members: Array<Member> = [];
|
members: Array<Member> = [];
|
||||||
filterId = 0;
|
filterId = 0;
|
||||||
|
dailyLockEnabled: false;
|
||||||
|
dailyStartTime: string;
|
||||||
|
dailyEndTime: string;
|
||||||
backlogColumn: KanbanColumn = new KanbanColumn();
|
backlogColumn: KanbanColumn = new KanbanColumn();
|
||||||
inprogressColumn: KanbanColumn = new KanbanColumn();
|
inprogressColumn: KanbanColumn = new KanbanColumn();
|
||||||
verificationColumn: KanbanColumn = new KanbanColumn();
|
verificationColumn: KanbanColumn = new KanbanColumn();
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user