* deploy config updated to deployer v4
* auto redirect to /kanban on page load * priority separator implemented * auto version reloader initial implementation
This commit is contained in:
parent
935af4c533
commit
f51b8090aa
3
.gitignore
vendored
3
.gitignore
vendored
@ -1,5 +1,8 @@
|
|||||||
# See http://help.github.com/ignore-files/ for more about ignoring files.
|
# See http://help.github.com/ignore-files/ for more about ignoring files.
|
||||||
|
|
||||||
|
# dynamic generated by deployer on remote host
|
||||||
|
revision.json
|
||||||
|
|
||||||
# compiled output
|
# compiled output
|
||||||
/semantic
|
/semantic
|
||||||
/dist
|
/dist
|
||||||
|
|||||||
@ -16,7 +16,7 @@ set('keep_releases', 3);
|
|||||||
set('default_stage', 'production');
|
set('default_stage', 'production');
|
||||||
|
|
||||||
// Servers
|
// Servers
|
||||||
server('vasgyuro', 'vasgyuro.tsp')
|
host('vasgyuro.tsp')
|
||||||
->stage('production')
|
->stage('production')
|
||||||
->user('edvidan')
|
->user('edvidan')
|
||||||
->forwardAgent()
|
->forwardAgent()
|
||||||
@ -40,6 +40,11 @@ task('deploy:ng-upload', function() {
|
|||||||
run("rm -f {{release_path}}/dist.tar.xz");
|
run("rm -f {{release_path}}/dist.tar.xz");
|
||||||
runLocally("rm -rf dist.tar.xz dist");
|
runLocally("rm -rf dist.tar.xz dist");
|
||||||
upload("htaccess", "{{release_path}}/dist/.htaccess");
|
upload("htaccess", "{{release_path}}/dist/.htaccess");
|
||||||
|
|
||||||
|
$revision = get("release_name");
|
||||||
|
within('{{release_path}}', function () use ($revision){
|
||||||
|
run("echo $revision > dist/revision.json");
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
desc('Deploy your project');
|
desc('Deploy your project');
|
||||||
|
|||||||
@ -7,7 +7,8 @@ import { KanbanBoardComponent } from "./kanban/kanban-board/kanban-board.compone
|
|||||||
const routes: Routes = [
|
const routes: Routes = [
|
||||||
{
|
{
|
||||||
path: '',
|
path: '',
|
||||||
children: []
|
redirectTo: '/kanban',
|
||||||
|
pathMatch: 'full',
|
||||||
},{
|
},{
|
||||||
path: 'kanban',
|
path: 'kanban',
|
||||||
children: [],
|
children: [],
|
||||||
|
|||||||
@ -4,7 +4,9 @@ import {TimerObservable} from "rxjs/observable/TimerObservable";
|
|||||||
|
|
||||||
import {KanbanService} from "./kanban/shared/kanban.service";
|
import {KanbanService} from "./kanban/shared/kanban.service";
|
||||||
import {Router} from "@angular/router";
|
import {Router} from "@angular/router";
|
||||||
|
import {SelfUpdaterService} from "./kanban/shared/self-updater.service";
|
||||||
|
|
||||||
|
const TIMER_DEPLOY_REFRESH = 30000;
|
||||||
const TIMER_JIRA_REFRESH = 60000;
|
const TIMER_JIRA_REFRESH = 60000;
|
||||||
const TIMER_PAGE_SWITCH = 300000;
|
const TIMER_PAGE_SWITCH = 300000;
|
||||||
|
|
||||||
@ -16,15 +18,21 @@ const TIMER_PAGE_SWITCH = 300000;
|
|||||||
})
|
})
|
||||||
export class AppComponent implements OnInit, OnDestroy {
|
export class AppComponent implements OnInit, OnDestroy {
|
||||||
|
|
||||||
|
selfUpdateCheckerTimer: Subscription;
|
||||||
reloadJiraIssueTimer: Subscription;
|
reloadJiraIssueTimer: Subscription;
|
||||||
pageSwitchTimer: Subscription;
|
pageSwitchTimer: Subscription;
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
|
private selfUpdaterService: SelfUpdaterService,
|
||||||
private kanbanService: KanbanService,
|
private kanbanService: KanbanService,
|
||||||
private router: Router
|
private router: Router
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
public ngOnInit() {
|
public ngOnInit() {
|
||||||
|
let timer0 = TimerObservable.create(TIMER_DEPLOY_REFRESH, TIMER_JIRA_REFRESH);
|
||||||
|
this.selfUpdateCheckerTimer = timer0.subscribe(() => {
|
||||||
|
this.selfUpdaterService.checkAndReloadIfNecessary();
|
||||||
|
});
|
||||||
let timer1 = TimerObservable.create(TIMER_JIRA_REFRESH, TIMER_JIRA_REFRESH);
|
let timer1 = TimerObservable.create(TIMER_JIRA_REFRESH, TIMER_JIRA_REFRESH);
|
||||||
this.reloadJiraIssueTimer = timer1.subscribe(() => {
|
this.reloadJiraIssueTimer = timer1.subscribe(() => {
|
||||||
this.kanbanService.reload();
|
this.kanbanService.reload();
|
||||||
@ -38,6 +46,7 @@ export class AppComponent implements OnInit, OnDestroy {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public ngOnDestroy() {
|
public ngOnDestroy() {
|
||||||
|
this.selfUpdateCheckerTimer.unsubscribe();
|
||||||
this.reloadJiraIssueTimer.unsubscribe();
|
this.reloadJiraIssueTimer.unsubscribe();
|
||||||
this.pageSwitchTimer.unsubscribe();
|
this.pageSwitchTimer.unsubscribe();
|
||||||
}
|
}
|
||||||
|
|||||||
@ -16,14 +16,36 @@
|
|||||||
border-radius: 4px;
|
border-radius: 4px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.ui.divided.items > .item:first-child {
|
.ui.divided.items > .item:last-child {
|
||||||
border-top: 0;
|
border-bottom: 0 !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
.ui.divided.items > .item {
|
.ui.divided.items > .item {
|
||||||
border-top: 1px solid rgba(250, 250, 250, 0.25);
|
border-bottom: 1px solid rgba(250, 250, 250, 0.25);
|
||||||
}
|
}
|
||||||
|
|
||||||
.ui.label {
|
.ui.label {
|
||||||
opacity: 0.85;
|
opacity: 0.85;
|
||||||
|
font-weight: bold;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.ui.divided.items > .item.blocker.bottom-separator {
|
||||||
|
border-bottom: 1px solid rgba(219, 40, 40, 0.5);
|
||||||
|
}
|
||||||
|
|
||||||
|
.ui.divided.items > .item.critical.bottom-separator {
|
||||||
|
border-bottom: 1px solid rgba(242, 113, 28, 0.5);
|
||||||
|
}
|
||||||
|
|
||||||
|
.ui.divided.items > .item.major.bottom-separator {
|
||||||
|
border-bottom: 1px solid rgba(181, 204, 24, 0.5);
|
||||||
|
}
|
||||||
|
|
||||||
|
.ui.divided.items > .item.minor.bottom-separator {
|
||||||
|
border-bottom: 1px solid rgba(0, 181, 173, 0.5);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*Nothing below trivial, no separator needed*/
|
||||||
|
/*.ui.divided.items > .item.trivial.bottom-separator {*/
|
||||||
|
/*border-bottom: 1px solid rgba(181, 204, 24, 0.5);*/
|
||||||
|
/*}*/
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
<h1>{{rowHeading}}</h1>
|
<h1>{{rowHeading}}</h1>
|
||||||
<div class="ui divided items">
|
<div class="ui divided items">
|
||||||
<div class="item" *ngFor="let kanbanEntry of kanbanEntries">
|
<div class="item {{kanbanEntry.issuePriority|lowercase}}" [ngClass]="entryClass(kanbanEntry)" *ngFor="let kanbanEntry of kanbanEntries">
|
||||||
<div class="content">
|
<div class="content">
|
||||||
<div class="task-description">
|
<div class="task-description">
|
||||||
<ng-template [ngIf]="hasLabels(kanbanEntry)">
|
<ng-template [ngIf]="hasLabels(kanbanEntry)">
|
||||||
|
|||||||
@ -40,4 +40,10 @@ export class KanbanEntryItemComponent implements OnInit {
|
|||||||
return 'white';
|
return 'white';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public entryClass(entry: KanbanEntry) {
|
||||||
|
return {
|
||||||
|
'bottom-separator': entry.isLastOfPriority,
|
||||||
|
};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -8,6 +8,7 @@ import { KanbanService } from './shared/kanban.service';
|
|||||||
import { KanbanEntryItemComponent } from './kanban-entry-item/kanban-entry-item.component';
|
import { KanbanEntryItemComponent } from './kanban-entry-item/kanban-entry-item.component';
|
||||||
import { PriorityColorPipe } from './shared/priority-color.pipe';
|
import { PriorityColorPipe } from './shared/priority-color.pipe';
|
||||||
import { ShortenTextPipe } from './shared/shorten-text.pipe';
|
import { ShortenTextPipe } from './shared/shorten-text.pipe';
|
||||||
|
import { SelfUpdaterService } from './shared/self-updater.service';
|
||||||
|
|
||||||
@NgModule({
|
@NgModule({
|
||||||
imports: [
|
imports: [
|
||||||
@ -22,6 +23,7 @@ import { ShortenTextPipe } from './shared/shorten-text.pipe';
|
|||||||
],
|
],
|
||||||
providers: [
|
providers: [
|
||||||
KanbanService,
|
KanbanService,
|
||||||
|
SelfUpdaterService,
|
||||||
],
|
],
|
||||||
exports: [],
|
exports: [],
|
||||||
})
|
})
|
||||||
|
|||||||
@ -9,7 +9,7 @@ export class KanbanEntry {
|
|||||||
public issueType: JiraIssueType;
|
public issueType: JiraIssueType;
|
||||||
public status: JiraStatus;
|
public status: JiraStatus;
|
||||||
public assignee: JiraAssignee;
|
public assignee: JiraAssignee;
|
||||||
public issuePriority: string
|
public issuePriority: string;
|
||||||
public issuePriorityIcon: string;
|
public issuePriorityIcon: string;
|
||||||
public labels: Array<string>;
|
public labels: Array<string>;
|
||||||
public prio: number;
|
public prio: number;
|
||||||
@ -22,4 +22,5 @@ export class KanbanEntry {
|
|||||||
public mhwebExternal: boolean;
|
public mhwebExternal: boolean;
|
||||||
public team: string;
|
public team: string;
|
||||||
public answerCode: string;
|
public answerCode: string;
|
||||||
|
public isLastOfPriority: boolean;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -18,7 +18,7 @@ export class KanbanService {
|
|||||||
constructor(private httpService: Http) {}
|
constructor(private httpService: Http) {}
|
||||||
|
|
||||||
public getList(): Observable<KanbanBoard> {
|
public getList(): Observable<KanbanBoard> {
|
||||||
return this.httpService.get(this.url).map(res => <KanbanBoard>res.json())
|
return this.httpService.get(this.url).map(res => this.preprocessPriorities(<KanbanBoard>res.json()));
|
||||||
}
|
}
|
||||||
|
|
||||||
public resolve(route: ActivatedRouteSnapshot): Promise<KanbanBoard> {
|
public resolve(route: ActivatedRouteSnapshot): Promise<KanbanBoard> {
|
||||||
@ -37,4 +37,25 @@ export class KanbanService {
|
|||||||
this.cachedKanbanBoard = kanbanBoard;
|
this.cachedKanbanBoard = kanbanBoard;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private preprocessPriorities(kanbanBoard: KanbanBoard): KanbanBoard {
|
||||||
|
['inbox','inProgress','verification','done'].map(progress => {
|
||||||
|
kanbanBoard[progress].map(entry => entry.isLastOfPriority = false);
|
||||||
|
['Trivial',
|
||||||
|
'Minor',
|
||||||
|
'Major',
|
||||||
|
'Critical',
|
||||||
|
'Blocker'].map(prio => {
|
||||||
|
let prioLastIndex = -1;
|
||||||
|
kanbanBoard[progress].map( (entry, idx) => {
|
||||||
|
if(entry.issuePriority == prio) {
|
||||||
|
prioLastIndex = idx;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
try {
|
||||||
|
kanbanBoard[progress][prioLastIndex].isLastOfPriority = true;
|
||||||
|
} catch(e) {}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
return kanbanBoard;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
15
src/app/kanban/shared/self-updater.service.spec.ts
Normal file
15
src/app/kanban/shared/self-updater.service.spec.ts
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
import { TestBed, inject } from '@angular/core/testing';
|
||||||
|
|
||||||
|
import { SelfUpdaterService } from './self-updater.service';
|
||||||
|
|
||||||
|
describe('SelfUpdaterService', () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
TestBed.configureTestingModule({
|
||||||
|
providers: [SelfUpdaterService]
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should be created', inject([SelfUpdaterService], (service: SelfUpdaterService) => {
|
||||||
|
expect(service).toBeTruthy();
|
||||||
|
}));
|
||||||
|
});
|
||||||
42
src/app/kanban/shared/self-updater.service.ts
Normal file
42
src/app/kanban/shared/self-updater.service.ts
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
import {Injectable} from '@angular/core';
|
||||||
|
import {Http} from "@angular/http";
|
||||||
|
import {Observable} from "rxjs/Observable";
|
||||||
|
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class SelfUpdaterService {
|
||||||
|
|
||||||
|
private appRevision: number = 0;
|
||||||
|
private initFailed: boolean = false;
|
||||||
|
|
||||||
|
constructor(private httpService: Http) {
|
||||||
|
console.log("init");
|
||||||
|
this.getDeployedRevision().subscribe(
|
||||||
|
result => this.appRevision = result,
|
||||||
|
() => {
|
||||||
|
console.log(
|
||||||
|
"%c Couldn't load initial revision data from server. Self update disabled.",
|
||||||
|
"background: #222; color: #bada55;"
|
||||||
|
);
|
||||||
|
this.initFailed = true;
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
private getDeployedRevision(): Observable<number> {
|
||||||
|
return this.httpService.get("/revision.json").map(result => result.json());
|
||||||
|
}
|
||||||
|
|
||||||
|
public checkAndReloadIfNecessary() {
|
||||||
|
if (!this.initFailed) {
|
||||||
|
this.getDeployedRevision().subscribe(
|
||||||
|
result => {
|
||||||
|
if (result > this.appRevision) {
|
||||||
|
document.location.reload(true);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
() => {}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
x
Reference in New Issue
Block a user