diff --git a/src/app/admin/admin-routing.module.ts b/src/app/admin/admin-routing.module.ts index 62fd0fe..cca431d 100644 --- a/src/app/admin/admin-routing.module.ts +++ b/src/app/admin/admin-routing.module.ts @@ -3,6 +3,8 @@ import { RouterModule, Routes } from '@angular/router'; import { TeamListComponent} from './team-list/team-list.component'; import { TeamService } from '../shared/service/team.service'; +import { TeamResolverService } from './team-resolver.service'; +import { TeamEditorComponent } from './team-editor/team-editor.component'; const routes: Routes = [ { @@ -12,6 +14,13 @@ const routes: Routes = [ resolve: { teams: TeamService, }, + }, { + path: 'admin/team/edit/:id', + component: TeamEditorComponent, + // canActivate: [AuthGuardService, RoleGuardService], + resolve: { + team: TeamResolverService, + }, } ]; diff --git a/src/app/admin/admin.module.ts b/src/app/admin/admin.module.ts index 0734b47..ca96824 100644 --- a/src/app/admin/admin.module.ts +++ b/src/app/admin/admin.module.ts @@ -1,15 +1,21 @@ import { NgModule } from '@angular/core'; import { CommonModule } from '@angular/common'; +import { FormsModule } from '@angular/forms'; import { AdminRoutingModule } from './admin-routing.module'; import { TeamListComponent } from './team-list/team-list.component'; +import { TeamEditorComponent } from './team-editor/team-editor.component'; +import { SlideEditorComponent } from './slide-editor/slide-editor.component'; +import { SlideListComponent } from './slide-list/slide-list.component'; +import { TeamResolverService } from './team-resolver.service'; @NgModule({ imports: [ CommonModule, + FormsModule, AdminRoutingModule ], - declarations: [TeamListComponent], - providers: [] + declarations: [TeamListComponent, TeamEditorComponent, SlideEditorComponent, SlideListComponent], + providers: [TeamResolverService] }) export class AdminModule { } diff --git a/src/app/admin/slide-editor/slide-editor.component.css b/src/app/admin/slide-editor/slide-editor.component.css new file mode 100644 index 0000000..e69de29 diff --git a/src/app/admin/slide-editor/slide-editor.component.html b/src/app/admin/slide-editor/slide-editor.component.html new file mode 100644 index 0000000..cdca987 --- /dev/null +++ b/src/app/admin/slide-editor/slide-editor.component.html @@ -0,0 +1,3 @@ +

+ slide-editor works! +

diff --git a/src/app/admin/slide-editor/slide-editor.component.spec.ts b/src/app/admin/slide-editor/slide-editor.component.spec.ts new file mode 100644 index 0000000..46c9006 --- /dev/null +++ b/src/app/admin/slide-editor/slide-editor.component.spec.ts @@ -0,0 +1,25 @@ +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; + +import { SlideEditorComponent } from './slide-editor.component'; + +describe('SlideEditorComponent', () => { + let component: SlideEditorComponent; + let fixture: ComponentFixture; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + declarations: [ SlideEditorComponent ] + }) + .compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(SlideEditorComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/admin/slide-editor/slide-editor.component.ts b/src/app/admin/slide-editor/slide-editor.component.ts new file mode 100644 index 0000000..6c6bb23 --- /dev/null +++ b/src/app/admin/slide-editor/slide-editor.component.ts @@ -0,0 +1,15 @@ +import { Component, OnInit } from '@angular/core'; + +@Component({ + selector: 'app-slide-editor', + templateUrl: './slide-editor.component.html', + styleUrls: ['./slide-editor.component.css'] +}) +export class SlideEditorComponent implements OnInit { + + constructor() { } + + ngOnInit() { + } + +} diff --git a/src/app/admin/slide-list/slide-list.component.css b/src/app/admin/slide-list/slide-list.component.css new file mode 100644 index 0000000..e69de29 diff --git a/src/app/admin/slide-list/slide-list.component.html b/src/app/admin/slide-list/slide-list.component.html new file mode 100644 index 0000000..a7c5219 --- /dev/null +++ b/src/app/admin/slide-list/slide-list.component.html @@ -0,0 +1,3 @@ +

+ slide-list works! +

diff --git a/src/app/admin/slide-list/slide-list.component.spec.ts b/src/app/admin/slide-list/slide-list.component.spec.ts new file mode 100644 index 0000000..4079f01 --- /dev/null +++ b/src/app/admin/slide-list/slide-list.component.spec.ts @@ -0,0 +1,25 @@ +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; + +import { SlideListComponent } from './slide-list.component'; + +describe('SlideListComponent', () => { + let component: SlideListComponent; + let fixture: ComponentFixture; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + declarations: [ SlideListComponent ] + }) + .compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(SlideListComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/admin/slide-list/slide-list.component.ts b/src/app/admin/slide-list/slide-list.component.ts new file mode 100644 index 0000000..fe12c15 --- /dev/null +++ b/src/app/admin/slide-list/slide-list.component.ts @@ -0,0 +1,15 @@ +import { Component, OnInit } from '@angular/core'; + +@Component({ + selector: 'app-slide-list', + templateUrl: './slide-list.component.html', + styleUrls: ['./slide-list.component.css'] +}) +export class SlideListComponent implements OnInit { + + constructor() { } + + ngOnInit() { + } + +} diff --git a/src/app/admin/team-editor/team-editor.component.css b/src/app/admin/team-editor/team-editor.component.css new file mode 100644 index 0000000..e69de29 diff --git a/src/app/admin/team-editor/team-editor.component.html b/src/app/admin/team-editor/team-editor.component.html new file mode 100644 index 0000000..e87c10c --- /dev/null +++ b/src/app/admin/team-editor/team-editor.component.html @@ -0,0 +1,53 @@ +
+

Team editor

+ +
+
+ + +
+ + +

Team members

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

+ + + + + + + + + + + + + + + +
SignumDisplay name
{{member.signum}}{{member.name}}
+ +
+
diff --git a/src/app/admin/team-editor/team-editor.component.spec.ts b/src/app/admin/team-editor/team-editor.component.spec.ts new file mode 100644 index 0000000..19fbf12 --- /dev/null +++ b/src/app/admin/team-editor/team-editor.component.spec.ts @@ -0,0 +1,25 @@ +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; + +import { TeamEditorComponent } from './team-editor.component'; + +describe('TeamEditorComponent', () => { + let component: TeamEditorComponent; + let fixture: ComponentFixture; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + declarations: [ TeamEditorComponent ] + }) + .compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(TeamEditorComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/admin/team-editor/team-editor.component.ts b/src/app/admin/team-editor/team-editor.component.ts new file mode 100644 index 0000000..fc86668 --- /dev/null +++ b/src/app/admin/team-editor/team-editor.component.ts @@ -0,0 +1,53 @@ +import { Component, OnInit } from '@angular/core'; +import { ActivatedRoute, Router } from '@angular/router'; +import { Title } from '@angular/platform-browser'; + +import { TeamService } from '../../shared/service/team.service'; +import { Team } from '../../shared/team'; +import { Member } from '../../shared/member'; + +@Component({ + selector: 'app-team-editor', + templateUrl: './team-editor.component.html', + styleUrls: ['./team-editor.component.css'] +}) +export class TeamEditorComponent implements OnInit { + public team: Team = new Team(); + public member: Member = new Member(); + + constructor(private teamService: TeamService, + private titleService: Title, + private route: ActivatedRoute, + private router: Router) { + } + + ngOnInit() { + this.titleService.setTitle('Team editor : MTAStv'); + this.route.data.subscribe((data: { team: Team }) => this.team = data.team); + } + + get canAddMember(): boolean { + try { + return [this.member.name, this.member.signum].every(field => field.length !== 0); + } catch (e) { + return false; + } + } + + public addMember() { + this.team.members = this.team.members.concat(Object.assign({}, this.member)); + this.member = new Member(); + } + + public removeMember(signum: String) { + if (confirm(`Remove the member with signum ${signum}?`)) { + this.team.members = this.team.members.filter(member => member.signum !== signum); + } + } + + public saveTeam() { + this.teamService.update(this.team).subscribe( + () => this.router.navigate(['/admin/teams/list']) + ); + } +} diff --git a/src/app/admin/team-list/team-list.component.html b/src/app/admin/team-list/team-list.component.html index 9570673..b2d3cf8 100644 --- a/src/app/admin/team-list/team-list.component.html +++ b/src/app/admin/team-list/team-list.component.html @@ -1,26 +1,22 @@

Teams

-
-
- - - - - - - - - - - - - - - -
TeamMembers
- - {{team.name}}{{fancyMemberNames(team)}}
-
-
+ + + + + + + + + + + + + + + +
TeamMembers
+ + {{team.name}}{{fancyMemberNames(team)}}
\ No newline at end of file diff --git a/src/app/admin/team-resolver.service.spec.ts b/src/app/admin/team-resolver.service.spec.ts new file mode 100644 index 0000000..ad37f56 --- /dev/null +++ b/src/app/admin/team-resolver.service.spec.ts @@ -0,0 +1,15 @@ +import { TestBed, inject } from '@angular/core/testing'; + +import { TeamResolverService } from './team-resolver.service'; + +describe('TeamResolverService', () => { + beforeEach(() => { + TestBed.configureTestingModule({ + providers: [TeamResolverService] + }); + }); + + it('should be created', inject([TeamResolverService], (service: TeamResolverService) => { + expect(service).toBeTruthy(); + })); +}); diff --git a/src/app/admin/team-resolver.service.ts b/src/app/admin/team-resolver.service.ts new file mode 100644 index 0000000..cecd095 --- /dev/null +++ b/src/app/admin/team-resolver.service.ts @@ -0,0 +1,21 @@ +import { Injectable } from '@angular/core'; +import { ActivatedRouteSnapshot, Resolve, RouterStateSnapshot } from '@angular/router'; +import { Team } from '../shared/team'; +import { environment } from '../../environments/environment'; +import { HttpClient } from '@angular/common/http'; +import { Observable } from 'rxjs/Observable'; + +@Injectable() +export class TeamResolverService implements Resolve { + private apiEndPoint = environment.apiUrl + '/api/team'; + + constructor(private httpClient: HttpClient) {} + + public resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Promise { + return this.getTeam(route.params['id']).toPromise(); + } + + public getTeam(id: Number): Observable { + return this.httpClient.get(`${this.apiEndPoint}/${id}`); + } +} diff --git a/src/app/display/commit-tracker/commit-tracker.component.css b/src/app/display/commit-tracker/commit-tracker.component.css index e69de29..3618bc0 100644 --- a/src/app/display/commit-tracker/commit-tracker.component.css +++ b/src/app/display/commit-tracker/commit-tracker.component.css @@ -0,0 +1,42 @@ +.ui.label.inprogress { + position: relative; +} + +.ui.label.inprogress::after { + content: ''; + opacity: 1; + position: absolute; + top: 0; + left: 0; + right: 0; + bottom: 0; + background: #ffffff; + border-radius: .28571429rem; + animation: label-progress-active 2.5s ease infinite; +} + +.ui.label.blue-yellow { + background: linear-gradient( + to top right, + #2185d0 45%, + #fbbd08 55%); +} + +.ui.label.blue-red { + background: linear-gradient( + to top right, + #2185d0 45%, + #db2828 55%); +} + +@keyframes label-progress-active { + 0% { + opacity: 0.5; + width: 0; + } + + 100% { + opacity: 0; + width: 100%; + } +} \ No newline at end of file diff --git a/src/app/display/commit-tracker/commit-tracker.component.html b/src/app/display/commit-tracker/commit-tracker.component.html index 2f67923..911fe85 100644 --- a/src/app/display/commit-tracker/commit-tracker.component.html +++ b/src/app/display/commit-tracker/commit-tracker.component.html @@ -1,35 +1,42 @@ -
-

Commit tracker

-
-
- +
+
- - - - - - + + + + + + + - - - - - - + + + + + + + -
Last activityChange subjectProjectBranchGerritStatusOwnerLast activityChange subjectProjectBranchGerritStatus
{{commit.gerrit_time}}{{commit.gerrit_change_subject}}{{commit.gerrit_project}}{{commit.branch}}{{commit.gerrit_change_number}} -
{{CommitStatus.Verified}}
-
{{CommitStatus.CodeReview}}
-
{{CommitStatus.CommitFeedbackLoop}}
-
{{CommitStatus.ShortFeedbackLoop}}
-
{{CommitStatus.NightlyFeedbackLoop}}
-
{{commit.owner}}{{commit.gerrit_time}}{{commit.gerrit_change_subject}}{{commit.gerrit_project}}{{commit.branch}}{{commit.gerrit_change_number}} +
{{CommitStatus.Verified}} +
+
{{CommitStatus.CodeReview}} +
+
{{CommitStatus.CommitFeedbackLoop}} +
+
{{CommitStatus.ShortFeedbackLoop}} +
+
{{CommitStatus.NightlyFeedbackLoop}} +
+
-
-
+
\ No newline at end of file diff --git a/src/app/display/commit-tracker/commit-tracker.component.ts b/src/app/display/commit-tracker/commit-tracker.component.ts index 9882651..8a25fad 100644 --- a/src/app/display/commit-tracker/commit-tracker.component.ts +++ b/src/app/display/commit-tracker/commit-tracker.component.ts @@ -6,6 +6,7 @@ import { CommitTrackerService } from '../../shared/service/commit-tracker.servic import { Commit } from '../../shared/commit'; import { CommitStatus } from '../../shared/commit-status.enum'; import { Result } from '../../shared/result.enum'; +import { Build } from '../../shared/build'; @Component({ selector: 'app-commit-tracker', @@ -18,11 +19,12 @@ export class CommitTrackerComponent implements OnInit { constructor(private commitTrackerService: CommitTrackerService, private titleService: Title, - private route: ActivatedRoute) {} + private route: ActivatedRoute) { + } ngOnInit() { this.titleService.setTitle('Commit-tracker : MTAStv'); - this.route.data.subscribe((data: {commits: Array}) => this.commits = data.commits); + this.route.data.subscribe((data: { commits: Array }) => this.commits = data.commits); } get commits(): Array { @@ -44,41 +46,77 @@ export class CommitTrackerComponent implements OnInit { switch (commitStatus) { case CommitStatus.Verified: return Object.assign(classes, { - green: commit.gerrit_verified === 2, - yellow: commit.gerrit_verified === 0, - red: commit.gerrit_verified === -2, + green: commit.gerrit_verified === 1, + red: commit.gerrit_verified === -1, }); case CommitStatus.CodeReview: return Object.assign(classes, { - green: commit.gerrit_code_review === 1, - yellow: commit.gerrit_code_review === 0, - red: commit.gerrit_code_review === -1, + green: commit.gerrit_code_review === 2, + yellow: commit.gerrit_code_review === 1 || commit.gerrit_code_review === -1, + red: commit.gerrit_code_review === -2, }); case CommitStatus.CommitFeedbackLoop: return Object.assign(classes, { + 'blue inprogress': commit.cfl_result === Result.Building, + 'blue-yellow inprogress': commit.cfl_result === Result.Building + && this.hasSubbuildWithCode(commit.cfl_sub_builds, Result.Unstable), + 'blue-red inprogress': commit.cfl_result === Result.Building + && this.hasSubbuildWithCode(commit.cfl_sub_builds, Result.Failure), green: commit.cfl_result === Result.Success, - yellow: commit.cfl_result === Result.Aborted, - orange: commit.cfl_result === Result.Unstable, + grey: commit.cfl_result === Result.Aborted, + yellow: commit.cfl_result === Result.Unstable, red: commit.cfl_result === Result.Failure, brown: commit.cfl_result === Result.NotBuilt, }); case CommitStatus.ShortFeedbackLoop: return Object.assign(classes, { + 'blue inprogress': commit.sfl_result === Result.Building, + 'blue-yellow inprogress': commit.sfl_result === Result.Building + && this.hasSubbuildWithCode(commit.sfl_sub_builds, Result.Unstable), + 'blue-red inprogress': commit.sfl_result === Result.Building + && this.hasSubbuildWithCode(commit.sfl_sub_builds, Result.Failure), green: commit.sfl_result === Result.Success, - yellow: commit.sfl_result === Result.Aborted, - orange: commit.sfl_result === Result.Unstable, + grey: commit.sfl_result === Result.Aborted, + yellow: commit.sfl_result === Result.Unstable, red: commit.sfl_result === Result.Failure, brown: commit.sfl_result === Result.NotBuilt, }); case CommitStatus.NightlyFeedbackLoop: return Object.assign(classes, { + 'blue inprogress': commit.nfl_result === Result.Building, + 'blue-yellow inprogress': commit.nfl_result === Result.Building + && this.hasSubbuildWithCode(commit.nfl_sub_builds, Result.Unstable), + 'blue-red inprogress': commit.nfl_result === Result.Building + && this.hasSubbuildWithCode(commit.nfl_sub_builds, Result.Failure), green: commit.nfl_result === Result.Success, - yellow: commit.nfl_result === Result.Aborted, + grey: commit.nfl_result === Result.Aborted, + yellow: commit.nfl_result === Result.Unstable, red: commit.nfl_result === Result.Failure, + brown: commit.nfl_result === Result.NotBuilt, }); + default: + return classes; + } + } + + private hasSubbuildWithCode(build: Build, status: Result): boolean { + if (build === null) { + return false; } - return classes; + try { + return build.build.subBuild.some(subBuild => { + let thing = false; + if (subBuild.build.subBuild) { + thing = subBuild.build.subBuild.some(subSubBuild => this.hasSubbuildWithCode( + subSubBuild, status + )); + } + return subBuild.result === status || thing; + }); + } catch (e) { + return false; + } } public rowClasses(commit: Commit) { diff --git a/src/app/shared/member.ts b/src/app/shared/member.ts index 4682662..3a572b6 100644 --- a/src/app/shared/member.ts +++ b/src/app/shared/member.ts @@ -1,4 +1,4 @@ export class Member { - signum: String; - name: String; + signum: String = ''; + name: String = ''; } diff --git a/src/app/shared/result.enum.ts b/src/app/shared/result.enum.ts index 7e70c8d..a580427 100644 --- a/src/app/shared/result.enum.ts +++ b/src/app/shared/result.enum.ts @@ -1,5 +1,6 @@ export enum Result { Aborted = 'ABORTED', + Building = 'BUILDING', Failure = 'FAILURE', NotBuilt = 'NOT_BUILT', Success = 'SUCCESS', diff --git a/src/app/shared/service/commit-tracker.service.ts b/src/app/shared/service/commit-tracker.service.ts index bd04278..dd1511d 100644 --- a/src/app/shared/service/commit-tracker.service.ts +++ b/src/app/shared/service/commit-tracker.service.ts @@ -1,5 +1,5 @@ import { Injectable } from '@angular/core'; -import { HttpClient } from '@angular/common/http'; +import { HttpClient, HttpParams, HttpHeaders } from '@angular/common/http'; import { ActivatedRouteSnapshot, Resolve, RouterStateSnapshot } from '@angular/router'; import { Observable } from 'rxjs/Observable'; @@ -21,9 +21,8 @@ export class CommitTrackerService implements Resolve> { } public getTeamCommits(signums: Array): Observable> { - return this.httpClient.post>(this.apiEndPoint, { - json_signums: signums - }); + const params = new HttpParams().set('json_signums', JSON.stringify(signums)); + return this.httpClient.get>(this.apiEndPoint, {params}); } get commits(): Array { diff --git a/src/app/shared/team.ts b/src/app/shared/team.ts index 2127d6d..1d14aa0 100644 --- a/src/app/shared/team.ts +++ b/src/app/shared/team.ts @@ -1,10 +1,10 @@ import { Member } from './member'; export class Team { - id: Number; - name: String; - members: Array; - isActive: boolean; - createdAt: String; - updatedAt: String; + id: Number = null; + name: String = ''; + members: Array = []; + isActive = false; + createdAt: String = null; + updatedAt: String = null; } diff --git a/src/styles.css b/src/styles.css index 009c911..7377efb 100644 --- a/src/styles.css +++ b/src/styles.css @@ -1,6 +1,10 @@ /* You can add global styles to this file, and also import other style files */ .main.container { - margin-top: 5em; + margin-top: 2em; +} + +.main.wide-container { + margin: 2em 2em 0 2em; } .ui.checkbox > label[for] {