From 58bb5071a59f4076e3d56433ec14bc0516d77d4c Mon Sep 17 00:00:00 2001 From: HardiReady Date: Sun, 12 Nov 2017 19:27:26 +0100 Subject: [PATCH 1/7] Mudulize war detail view --- .gitignore | 3 +- package.json | 2 +- static/src/app/app.component.html | 2 +- static/src/app/app.routing.ts | 16 +- static/src/app/statistic/stats.routing.ts | 6 +- .../war-detail-header.component.css | 15 + .../war-detail-header.component.html | 66 +++ .../war-detail-header.component.ts | 49 +++ .../war-detail/war-detail.component.css | 21 - .../war-detail/war-detail.component.html | 185 +++------ .../war-detail/war-detail.component.ts | 382 ++---------------- .../statistic/war-list/war-list.component.ts | 1 - static/src/styles.css | 8 + 13 files changed, 228 insertions(+), 528 deletions(-) create mode 100644 static/src/app/statistic/war-detail-header/war-detail-header.component.css create mode 100644 static/src/app/statistic/war-detail-header/war-detail-header.component.html create mode 100644 static/src/app/statistic/war-detail-header/war-detail-header.component.ts diff --git a/.gitignore b/.gitignore index 1217825..33bef2c 100644 --- a/.gitignore +++ b/.gitignore @@ -44,7 +44,8 @@ Thumbs.db .directory # Internal Data -/public +public/ +mongodb-data/ resource/ backup/ diff --git a/package.json b/package.json index 346f498..4ee7696 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "opt-cc", - "version": "1.6.3", + "version": "1.6.4", "license": "MIT", "author": "Florian Hartwich ", "private": true, diff --git a/static/src/app/app.component.html b/static/src/app/app.component.html index c3cc9d9..6d4433a 100644 --- a/static/src/app/app.component.html +++ b/static/src/app/app.component.html @@ -96,6 +96,6 @@ diff --git a/static/src/app/app.routing.ts b/static/src/app/app.routing.ts index c9ed43c..06eecf2 100644 --- a/static/src/app/app.routing.ts +++ b/static/src/app/app.routing.ts @@ -58,14 +58,14 @@ export const appRoutes: Routes = [ }, /** Redirect Configuration **/ - { - path: '404', - component: NotFoundComponent - }, - { - path: '**', - redirectTo: '/404' - } // always configure this last - first matching route gets processed + // { + // path: '404', + // component: NotFoundComponent + // }, + // { + // path: '**', + // redirectTo: '/404' + // } // always configure this last - first matching route gets processed ]; export const appRouting = RouterModule.forRoot(appRoutes); diff --git a/static/src/app/statistic/stats.routing.ts b/static/src/app/statistic/stats.routing.ts index dbc6951..a1e914a 100644 --- a/static/src/app/statistic/stats.routing.ts +++ b/static/src/app/statistic/stats.routing.ts @@ -8,6 +8,7 @@ import {WarItemComponent} from "./war-list/war-item.component"; import {ModuleWithProviders} from "@angular/core"; import {CampaignSubmitComponent} from "./campaign-submit/campaign-submit.component"; import {CampaignPlayerDetailComponent} from "./campaign-player-detail/campaign-player-detail.component"; +import {WarDetailHeaderComponent} from "./war-detail-header/war-detail-header.component"; export const statsRoutes: Routes = [{ @@ -36,7 +37,7 @@ export const statsRoutes: Routes = [{ }, { path: 'war/:id', - component: WarDetailComponent, + component: WarDetailHeaderComponent, outlet: 'right' }, { @@ -48,5 +49,6 @@ export const statsRoutes: Routes = [{ export const statsRouterModule: ModuleWithProviders = RouterModule.forChild(statsRoutes); export const statsRoutingComponents = [StatisticComponent, StatisticOverviewComponent, CampaignSubmitComponent, - WarListComponent, WarSubmitComponent, WarDetailComponent, CampaignPlayerDetailComponent, WarItemComponent]; + WarListComponent, WarSubmitComponent, WarDetailHeaderComponent, WarDetailComponent, CampaignPlayerDetailComponent, + WarItemComponent]; diff --git a/static/src/app/statistic/war-detail-header/war-detail-header.component.css b/static/src/app/statistic/war-detail-header/war-detail-header.component.css new file mode 100644 index 0000000..d727ec1 --- /dev/null +++ b/static/src/app/statistic/war-detail-header/war-detail-header.component.css @@ -0,0 +1,15 @@ +.war-header-container { + width: 920px; + min-height: 205px; + margin: auto; +} + +.head-field { + font-size: 24px; + margin-top: 10px; + margin-bottom: 10px; +} + +.war-header { + border-bottom: thin solid lightgrey; +} diff --git a/static/src/app/statistic/war-detail-header/war-detail-header.component.html b/static/src/app/statistic/war-detail-header/war-detail-header.component.html new file mode 100644 index 0000000..a5c31c3 --- /dev/null +++ b/static/src/app/statistic/war-detail-header/war-detail-header.component.html @@ -0,0 +1,66 @@ +
+
+

{{war.title}} - vom {{war.date | date: 'dd.MM.yyyy'}}

+
+

Endpunktestand:

+ {{fraction.BLUFOR}} {{war.ptBlufor}} + | + {{war.ptOpfor}} {{fraction.OPFOR}} +
+ +
+

Teilnehmer:

+ + +
+ +
+ Logfile + anzeigen +
+ + + +
+
+
+
+ + + + + + +
diff --git a/static/src/app/statistic/war-detail-header/war-detail-header.component.ts b/static/src/app/statistic/war-detail-header/war-detail-header.component.ts new file mode 100644 index 0000000..f17b40c --- /dev/null +++ b/static/src/app/statistic/war-detail-header/war-detail-header.component.ts @@ -0,0 +1,49 @@ +import {Component} from "@angular/core"; +import {ActivatedRoute} from "@angular/router"; +import {WarService} from "../../services/logs/war.service"; +import {War} from "../../models/model-interfaces"; +import {ChartUtils} from "../../utils/chart-utils"; +import {Fraction} from "../../utils/fraction.enum"; + + +@Component({ + selector: 'war-detail-header', + templateUrl: './war-detail-header.component.html', + styleUrls: ['./war-detail-header.component.css', '../../style/list-entry.css', '../../style/hide-scrollbar.css'] +}) +export class WarDetailHeaderComponent { + + readonly fraction = Fraction; + + war: War; + + fractionFilterSelected: string; + + playerChart: any[] = []; + + colorScheme = { + domain: [Fraction.COLOR_OPFOR, Fraction.COLOR_BLUFOR] + }; + + constructor(private route: ActivatedRoute, + private warService: WarService) { + } + + ngOnInit() { + this.route.params + .map(params => params['id']) + .filter(id => id != undefined) + .flatMap(id => this.warService.getWar(id)) + .subscribe(war => { + this.war = war; + this.fractionFilterSelected = undefined; + this.playerChart = ChartUtils.getSingleDataArray(Fraction.OPFOR, war.playersOpfor, Fraction.BLUFOR, war.playersBlufor); + Object.assign(this, [this.playerChart]); + }) + } + + filterPlayersByFraction(fraction?: string) { + this.fractionFilterSelected = fraction; + } + +} diff --git a/static/src/app/statistic/war-detail/war-detail.component.css b/static/src/app/statistic/war-detail/war-detail.component.css index ac69342..5716be4 100644 --- a/static/src/app/statistic/war-detail/war-detail.component.css +++ b/static/src/app/statistic/war-detail/war-detail.component.css @@ -34,27 +34,6 @@ font-weight: bold; } -/* ########### TABS ########### */ - -:host /deep/ .nav-tabs { - padding-left: 35% !important; -} - -:host /deep/ .nav-link { - background: #4b4b4b; - color: white; -} - -:host /deep/ .nav-link:hover { - background: #afafaf; - color: #000; -} - -:host /deep/ .nav-tabs > li.active > a { - background: #222222; - color: white; -} - /* ########### DATATABLE ########### */ :host /deep/ .datatable-header { diff --git a/static/src/app/statistic/war-detail/war-detail.component.html b/static/src/app/statistic/war-detail/war-detail.component.html index 306a641..3a1b31e 100644 --- a/static/src/app/statistic/war-detail/war-detail.component.html +++ b/static/src/app/statistic/war-detail/war-detail.component.html @@ -1,63 +1,7 @@
-
-
-
-

{{war.title}} - vom {{war.date | date: 'dd.MM.yyyy'}}

-
-

Endpunktestand:

- {{fraction.BLUFOR}} {{war.ptBlufor}} - | - {{war.ptOpfor}} {{fraction.OPFOR}} -
-
-

Teilnehmer:

- - -
- -
- Logfile anzeigen -
- - - -
-
-
-
-
- - - - - Scoreboard - -
-
- - - Fraktionen - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + -
- - - - - - - - -
+ + + + + + + + + + + + + + + + + -
- - -
- -
- - -
-
- - - - - - -
+ + + + + + + + + + + + + + + + +
diff --git a/static/src/app/statistic/war-detail/war-detail.component.ts b/static/src/app/statistic/war-detail/war-detail.component.ts index 99b39d2..cdea6c5 100644 --- a/static/src/app/statistic/war-detail/war-detail.component.ts +++ b/static/src/app/statistic/war-detail/war-detail.component.ts @@ -1,18 +1,13 @@ -/// -import {Component, ElementRef, ViewChild} from "@angular/core"; +import {Component, ElementRef, SimpleChanges, ViewChild} from "@angular/core"; import {ActivatedRoute, Router} from "@angular/router"; -import {WarService} from "../../services/logs/war.service"; import {War} from "../../models/model-interfaces"; -import {LogsService} from "../../services/logs/logs.service"; -import {TabsetComponent} from "ngx-bootstrap"; -import * as d3 from "d3"; -import {ChartUtils} from "../../utils/chart-utils"; import {Fraction} from "../../utils/fraction.enum"; @Component({ selector: 'war-detail', templateUrl: './war-detail.component.html', + inputs: ['war', 'fractionFilterSelected'], styleUrls: ['./war-detail.component.css', '../../style/list-entry.css', '../../style/hide-scrollbar.css'] }) export class WarDetailComponent { @@ -21,21 +16,9 @@ export class WarDetailComponent { @ViewChild('overview') private overviewContainer: ElementRef; - @ViewChild('staticTabs') staticTabs: TabsetComponent; + war: War; - war: War = {players: []}; - - logData: any; - - initialized: any; - - startDateObj: Date; - - public chartSelectModel: string; - - fractionRadioSelect: string; - - playerChart: any[] = []; + fractionFilterSelected: string; cellHeight = 40; @@ -48,80 +31,35 @@ export class WarDetailComponent { sortDescending: 'glyphicon glyphicon-triangle-bottom', }; - lineChartData: any[] = []; - areaChartData: any[] = []; - - tmpPointData; - tmpBudgetData; - tmpKillData; - tmpFrienlyFireData; - tmpTransportData; - tmpReviveData; - tmpStabilizeData; - tmpFlagCaptureData; - - colorScheme = { - domain: [Fraction.COLOR_BLUFOR, Fraction.COLOR_OPFOR] - }; - - labelPoints = 'Punkte'; - labelBudget = 'Budget'; - labelKill = 'Kills'; - labelFriendlyFire = 'FriendlyFire'; - labelTransport = 'Lufttransport'; - labelRevive = 'Revive'; - labelStabilize = 'Stabilisiert'; - labelFlag = 'Flaggenbesitz'; - lineChartLabel: string = this.labelPoints; - - showLineChart = true; - stepCurve = d3.curveStepAfter; - gradient = false; - yAxis = true; - xAxis = true; - legend = false; - legendTitle = false; - showXAxisLabel = false; - showYAxisLabel = true; - autoscale = true; - timeline = false; - roundDomains = true; - constructor(private route: ActivatedRoute, - private router: Router, - private warService: WarService, - private logsService: LogsService) { + private router: Router) { } ngOnInit() { - this.route.params - .map(params => params['id']) - .filter(id => id != undefined) - .flatMap(id => this.warService.getWar(id)) - .subscribe(war => { - this.war = war; - this.rows = war.players; - this.playerChart = ChartUtils.getSingleDataArray(Fraction.OPFOR, war.playersOpfor, Fraction.BLUFOR, war.playersBlufor); + } - this.initialized = { - basic: false, - budget: false, - kill: false, - revive: false, - transport: false, - flag: false - }; - Object.assign(this, [this.playerChart, this.lineChartData, this.areaChartData]); - this.chartSelectModel = this.labelPoints; + selectPlayerDetail(player) { + if (player && player.selected && player.selected.length > 0) { + this.router.navigate(['../../campaign-player/' + this.war.campaign + '/' + player.selected[0].name], + {relativeTo: this.route}); + } + } - this.startDateObj = new Date(this.war.date); - this.startDateObj.setHours(0); - this.startDateObj.setMinutes(1); + ngOnChanges(changes: SimpleChanges) { + if (changes.war) { + this.rows = changes.war.currentValue.players; + } + if (changes.fractionFilterSelected) { + this.filterPlayersByFraction(this.fractionFilterSelected) + } + this.scrollOverviewTop(); + } - this.fractionRadioSelect = undefined; - this.staticTabs.tabs[0].active = true; - this.scrollOverviewTop(); - }); + scrollOverviewTop() { + try { + this.overviewContainer.nativeElement.scrollTop = 0; + } catch (err) { + } } filterPlayersByFraction(fraction?: string) { @@ -134,272 +72,4 @@ export class WarDetailComponent { } } - selectChart() { - if (this.chartSelectModel !== this.labelFlag) { - this.showLineChart = true; - this.lineChartLabel = this.chartSelectModel; - switch (this.chartSelectModel) { - case this.labelPoints: - this.lineChartData = this.tmpPointData; - break; - case this.labelBudget: - this.initBudgetData(); - this.lineChartData = this.tmpBudgetData; - break; - case this.labelKill: - this.initKillData(); - this.lineChartData = this.tmpKillData; - break; - case this.labelFriendlyFire: - this.initKillData(); - this.lineChartData = this.tmpFrienlyFireData; - break; - case this.labelRevive: - this.initRevive(); - this.lineChartData = this.tmpReviveData; - break; - case this.labelStabilize: - this.initRevive(); - this.lineChartData = this.tmpStabilizeData; - break; - case this.labelTransport: - this.initTransportData(); - this.lineChartData = this.tmpTransportData; - break; - } - } else { - this.initFlagHoldData(); - this.showLineChart = false; - this.areaChartData = this.tmpFlagCaptureData; - } - } - - selectPlayerDetail(player) { - if (player && player.selected && player.selected.length > 0) { - this.router.navigate(['../../campaign-player/' + this.war.campaign + '/' + player.selected[0].name], - {relativeTo: this.route}); - } - } - - scrollOverviewTop() { - try { - this.overviewContainer.nativeElement.scrollTop = 0; - } catch (err) { - } - } - - loadFractionData() { - if (this.initialized.basic) { - return; - } - - this.initializeTempCollections(); - - this.logsService.getFullLog(this.war._id).subscribe((data) => { - this.logData = data; - this.initPointData(); - this.showLineChart = true; - this.lineChartLabel = this.labelPoints; - this.lineChartData = this.tmpPointData; - this.initialized.basic = true; - }); - } - - initPointData() { - this.logData.points.forEach(pointEntry => { - this.tmpPointData[0].series.push(ChartUtils.getSeriesEntry(new Date(pointEntry.time), pointEntry.ptBlufor)); - this.tmpPointData[1].series.push(ChartUtils.getSeriesEntry(new Date(pointEntry.time), pointEntry.ptOpfor)); - }); - this.addFinalTimeData(this.tmpPointData); - } - - initBudgetData() { - if (this.initialized.budget) { - return; - } - this.logData.budget.forEach(budgetEntry => { - const budgetEntryDate = new Date(budgetEntry.time); - const fractionChange = budgetEntry.fraction === 'BLUFOR' ? 0 : 1; - const fractionOld = budgetEntry.fraction !== 'BLUFOR' ? 0 : 1; - - if (WarDetailComponent.isTwoMinutesAhead(budgetEntryDate, this.tmpBudgetData)) { - this.tmpBudgetData[fractionChange].series.push(ChartUtils.getSeriesEntry(new Date(budgetEntry.time), budgetEntry.newBudget)); - this.tmpBudgetData[fractionOld].series.push(ChartUtils.getSeriesEntry(new Date(budgetEntry.time), - this.tmpBudgetData[fractionOld].series[this.tmpBudgetData[fractionOld].series.length - 1].value)); - } - }); - this.addFinalTimeData(this.tmpBudgetData); - this.initialized.budget = true; - } - - initKillData() { - if (this.initialized.kill) { - return; - } - let killCountBlufor = 0, killCountOpfor = 0, ffKillCountBlufor = 0, ffKillCountOpfor = 0; - - for (const {killEntry, index} of this.logData.kill.map((killEntry, index) => ({killEntry, index}))) { - const killEntryDate = new Date(killEntry.time); - if (killEntry.friendlyFire === false) { - if (killEntry.fraction === 'BLUFOR') { - killCountBlufor++; - } - if (killEntry.fraction === 'OPFOR') { - killCountOpfor++; - } - if (WarDetailComponent.isTwoMinutesAhead(killEntryDate, this.tmpKillData)) { - this.tmpKillData[0].series.push(ChartUtils.getSeriesEntry(killEntryDate, killCountBlufor)); - this.tmpKillData[1].series.push(ChartUtils.getSeriesEntry(killEntryDate, killCountOpfor)); - } - } else { - if (killEntry.fraction === 'BLUFOR') { - ffKillCountBlufor++; - } - if (killEntry.fraction === 'OPFOR') { - ffKillCountOpfor++; - } - if (WarDetailComponent.isTwoMinutesAhead(killEntryDate, this.tmpFrienlyFireData)) { - this.tmpFrienlyFireData[0].series.push(ChartUtils.getSeriesEntry(killEntryDate, ffKillCountBlufor)); - this.tmpFrienlyFireData[1].series.push(ChartUtils.getSeriesEntry(killEntryDate, ffKillCountOpfor)); - } - } - if (index === this.logData.kill.length - 1) { - this.tmpKillData[0].series.push(ChartUtils.getSeriesEntry(killEntryDate, killCountBlufor)); - this.tmpKillData[1].series.push(ChartUtils.getSeriesEntry(killEntryDate, killCountOpfor)); - this.tmpFrienlyFireData[0].series.push(ChartUtils.getSeriesEntry(killEntryDate, ffKillCountBlufor)); - this.tmpFrienlyFireData[1].series.push(ChartUtils.getSeriesEntry(killEntryDate, ffKillCountOpfor)); - } - } - - this.addFinalTimeData(this.tmpKillData); - this.addFinalTimeData(this.tmpFrienlyFireData) - this.initialized.kill = true; - } - - initRevive() { - if (this.initialized.revive) { - return; - } - let reviveCountBlufor = 0, reviveCountOpfor = 0, stabilizeCountBlufor = 0, stabilizeCountOpfor = 0; - for (const {reviveEntry, index} of this.logData.revive.map((reviveEntry, index) => ({reviveEntry, index}))) { - const reviveEntryDate = new Date(reviveEntry.time); - if (reviveEntry.stabilized === false) { - if (reviveEntry.fraction === 'BLUFOR') { - reviveCountBlufor++; - } else { - reviveCountOpfor++; - } - if (WarDetailComponent.isTwoMinutesAhead(reviveEntryDate, this.tmpReviveData)) { - this.tmpReviveData[0].series.push(ChartUtils.getSeriesEntry(reviveEntryDate, reviveCountBlufor)); - this.tmpReviveData[1].series.push(ChartUtils.getSeriesEntry(reviveEntryDate, reviveCountOpfor)); - } - } else { - if (reviveEntry.fraction === 'BLUFOR') { - stabilizeCountBlufor++; - } else { - stabilizeCountOpfor++; - } - if (WarDetailComponent.isTwoMinutesAhead(reviveEntryDate, this.tmpStabilizeData)) { - this.tmpStabilizeData[0].series.push(ChartUtils.getSeriesEntry(reviveEntryDate, stabilizeCountBlufor)); - this.tmpStabilizeData[1].series.push(ChartUtils.getSeriesEntry(reviveEntryDate, stabilizeCountOpfor)); - } - } - if (index === this.logData.revive.length - 1) { - this.tmpReviveData[0].series.push(ChartUtils.getSeriesEntry(reviveEntryDate, reviveCountBlufor)); - this.tmpReviveData[1].series.push(ChartUtils.getSeriesEntry(reviveEntryDate, reviveCountOpfor)); - this.tmpStabilizeData[0].series.push(ChartUtils.getSeriesEntry(reviveEntryDate, stabilizeCountBlufor)); - this.tmpStabilizeData[1].series.push(ChartUtils.getSeriesEntry(reviveEntryDate, stabilizeCountOpfor)); - } - } - this.addFinalTimeData(this.tmpReviveData); - this.addFinalTimeData(this.tmpStabilizeData); - this.initialized.revive = true; - } - - initTransportData() { - if (this.initialized.transport) { - return; - } - let transportCountBlufor = 0, transportCountOpfor = 0; - for (const {transportEntry, index} of this.logData.transport.map((transportEntry, index) => ({ - transportEntry, - index - }))) { - const transportEntryDate = new Date(transportEntry.time); - if (transportEntry.fraction === 'BLUFOR') { - transportCountBlufor++; - } else { - transportCountOpfor++; - } - if (WarDetailComponent.isTwoMinutesAhead(transportEntryDate, this.tmpTransportData) || index === this.logData.transport.length - 1) { - this.tmpTransportData[0].series.push(ChartUtils.getSeriesEntry(transportEntryDate, transportCountBlufor)); - this.tmpTransportData[1].series.push(ChartUtils.getSeriesEntry(transportEntryDate, transportCountOpfor)); - } - } - this.addFinalTimeData(this.tmpTransportData); - this.initialized.transport = true; - - } - - initFlagHoldData() { - if (this.initialized.flag) { - return; - } - let flagStatusBlufor = true; - let flagStatusOpfor = true; - this.tmpFlagCaptureData[0].series.push(ChartUtils.getSeriesEntry(this.startDateObj, flagStatusBlufor)); - this.tmpFlagCaptureData[1].series.push(ChartUtils.getSeriesEntry(this.startDateObj, flagStatusOpfor)); - - this.logData.flag.forEach(flagEntry => { - if (flagEntry.flagFraction === 'BLUFOR') { - flagStatusBlufor = !flagEntry.capture; - } else { - flagStatusOpfor = !flagEntry.capture; - } - this.tmpFlagCaptureData[flagEntry.flagFraction === 'BLUFOR' ? 0 : 1].series.push( - ChartUtils.getSeriesEntry(new Date(flagEntry.time), flagEntry.flagFraction === 'BLUFOR' ? flagStatusBlufor : flagStatusOpfor) - ) - }); - - this.addFinalTimeData(this.tmpFlagCaptureData); - this.initialized.flag = true; - } - - private static isTwoMinutesAhead(entryDate: Date, tmpData: any): boolean { - return entryDate.getTime() >= tmpData[0].series[tmpData[0].series.length - 1].name.getTime() + (1.5 * 60000) - } - - initializeTempCollections() { - this.tmpPointData = ChartUtils.getMultiDataArray(Fraction.BLUFOR, Fraction.OPFOR); - this.tmpBudgetData = ChartUtils.getMultiDataArray(Fraction.BLUFOR, Fraction.OPFOR); - this.tmpKillData = ChartUtils.getMultiDataArray(Fraction.BLUFOR, Fraction.OPFOR); - this.tmpFrienlyFireData = ChartUtils.getMultiDataArray(Fraction.BLUFOR, Fraction.OPFOR); - this.tmpTransportData = ChartUtils.getMultiDataArray(Fraction.BLUFOR, Fraction.OPFOR); - this.tmpReviveData = ChartUtils.getMultiDataArray(Fraction.BLUFOR, Fraction.OPFOR); - this.tmpStabilizeData = ChartUtils.getMultiDataArray(Fraction.BLUFOR, Fraction.OPFOR); - this.tmpFlagCaptureData = ChartUtils.getMultiDataArray(Fraction.BLUFOR, Fraction.OPFOR); - - [this.tmpKillData, this.tmpFrienlyFireData, this.tmpReviveData, this.tmpStabilizeData, this.tmpTransportData].forEach(tmp => { - [0, 1].forEach(index => { - tmp[index].series.push(ChartUtils.getSeriesEntry(this.startDateObj, 0)); - }) - }); - this.tmpBudgetData[0].series.push(ChartUtils.getSeriesEntry(this.startDateObj, this.war.budgetBlufor)); - this.tmpBudgetData[1].series.push(ChartUtils.getSeriesEntry(this.startDateObj, this.war.budgetOpfor)); - } - - addFinalTimeData(tmpCollection) { - const endDate = new Date(this.war.endDate); - if (tmpCollection === this.tmpBudgetData) { - this.tmpBudgetData[0].series.push(ChartUtils.getSeriesEntry(endDate, this.war.endBudgetBlufor)); - this.tmpBudgetData[1].series.push(ChartUtils.getSeriesEntry(endDate, this.war.endBudgetOpfor)); - } else { - for (let j in [0, 1]) { - if (tmpCollection[j].series[tmpCollection[j].series.length - 1].name < endDate) { - tmpCollection[j].series.push(ChartUtils.getSeriesEntry(endDate, tmpCollection[j].series[tmpCollection[j].series.length - 1].value)); - } - } - } - } - } diff --git a/static/src/app/statistic/war-list/war-list.component.ts b/static/src/app/statistic/war-list/war-list.component.ts index f109160..4f6eb9a 100644 --- a/static/src/app/statistic/war-list/war-list.component.ts +++ b/static/src/app/statistic/war-list/war-list.component.ts @@ -82,7 +82,6 @@ export class WarListComponent implements OnInit { if (confirm('Soll die Kampagne ' + campaign.title + ' wirklich gelöscht werden?')) { this.campaignService.deleteCampaign(campaign._id) .subscribe((res) => { - console.log(res) if (this.selectedWarId === campaign._id) { this.selectOverview('all'); } diff --git a/static/src/styles.css b/static/src/styles.css index ab03687..1eda07a 100644 --- a/static/src/styles.css +++ b/static/src/styles.css @@ -47,3 +47,11 @@ form { #right { overflow: hidden; } + +#right-top { + overflow: hidden; +} + +#right-bottom { + overflow: hidden; +} From c6d55011b6b4916260a871ee3e014d56ff54568b Mon Sep 17 00:00:00 2001 From: HardiReady Date: Sun, 12 Nov 2017 23:32:31 +0100 Subject: [PATCH 2/7] Add extra component for fraction war stats --- static/src/app/statistic/stats.routing.ts | 5 +- .../war-detail-fraction.component.css | 129 +++++++ .../war-detail-fraction.component.html | 74 ++++ .../war-detail-fraction.component.ts | 344 ++++++++++++++++++ .../war-detail-header.component.css | 13 + .../war-detail-header.component.html | 12 +- .../war-detail/war-detail.component.html | 53 --- 7 files changed, 571 insertions(+), 59 deletions(-) create mode 100644 static/src/app/statistic/war-detail-fraction/war-detail-fraction.component.css create mode 100644 static/src/app/statistic/war-detail-fraction/war-detail-fraction.component.html create mode 100644 static/src/app/statistic/war-detail-fraction/war-detail-fraction.component.ts diff --git a/static/src/app/statistic/stats.routing.ts b/static/src/app/statistic/stats.routing.ts index a1e914a..92b1188 100644 --- a/static/src/app/statistic/stats.routing.ts +++ b/static/src/app/statistic/stats.routing.ts @@ -9,6 +9,7 @@ import {ModuleWithProviders} from "@angular/core"; import {CampaignSubmitComponent} from "./campaign-submit/campaign-submit.component"; import {CampaignPlayerDetailComponent} from "./campaign-player-detail/campaign-player-detail.component"; import {WarDetailHeaderComponent} from "./war-detail-header/war-detail-header.component"; +import {WarDetailFractionComponent} from "./war-detail-fraction/war-detail-fraction.component"; export const statsRoutes: Routes = [{ @@ -49,6 +50,6 @@ export const statsRoutes: Routes = [{ export const statsRouterModule: ModuleWithProviders = RouterModule.forChild(statsRoutes); export const statsRoutingComponents = [StatisticComponent, StatisticOverviewComponent, CampaignSubmitComponent, - WarListComponent, WarSubmitComponent, WarDetailHeaderComponent, WarDetailComponent, CampaignPlayerDetailComponent, - WarItemComponent]; + WarListComponent, WarSubmitComponent, WarDetailHeaderComponent, WarDetailComponent, WarDetailFractionComponent, + CampaignPlayerDetailComponent, WarItemComponent]; diff --git a/static/src/app/statistic/war-detail-fraction/war-detail-fraction.component.css b/static/src/app/statistic/war-detail-fraction/war-detail-fraction.component.css new file mode 100644 index 0000000..ac69342 --- /dev/null +++ b/static/src/app/statistic/war-detail-fraction/war-detail-fraction.component.css @@ -0,0 +1,129 @@ +.vertical-spacer { + height: 205px; + float: left; + width: 4%; +} + +.head-field { + font-size: 24px; + margin-top: 10px; + margin-bottom: 10px; +} + +@media screen and (min-width: 1500px) { + .vertical-spacer { + width: 15%; + } +} + +@media screen and (min-width: 2000px) { + .vertical-spacer { + width: 20%; + } +} + +.overview { + overflow-y: scroll; + overflow-x: hidden; + border-left: thin solid lightgrey; + bottom: 20px; + height: 100vh; +} + +.player-name { + font-weight: bold; +} + +/* ########### TABS ########### */ + +:host /deep/ .nav-tabs { + padding-left: 35% !important; +} + +:host /deep/ .nav-link { + background: #4b4b4b; + color: white; +} + +:host /deep/ .nav-link:hover { + background: #afafaf; + color: #000; +} + +:host /deep/ .nav-tabs > li.active > a { + background: #222222; + color: white; +} + +/* ########### DATATABLE ########### */ + +:host /deep/ .datatable-header { + background: #222222; + font-weight: 700; + border-radius: 10px 10px 0 0; + color: white; +} + +:host /deep/ span.datatable-header-cell-label, :host /deep/ div.datatable-body-cell-label { + padding-left: 8px; +} + +:host /deep/ .ngx-datatable .datatable-header { + /*vertical center alignment*/ + display: table-cell; + vertical-align: middle; +} + +:host /deep/ .ngx-datatable .datatable-body .datatable-body-row > div { + /*vertical alignment*/ + position: relative; + top: 10px; +} + +:host /deep/ .datatable-body-row { + color: #222222; + border-bottom: 1px solid grey; + cursor: pointer; +} + +:host /deep/ .datatable-body-row:hover { + background-color: #f7f7f7; +} + +/* ########### CHART-TAB ######## */ + +.btn-dark { + background: #4b4b4b; + color: #f5f5f5; + border-color: #000; +} + +.btn-dark:hover { + background: #afafaf; + color: #f5f5f5; +} + +.btn-dark.active { + background: #222222; +} + +.chart-container { + width: 95%; + margin: 2%; + min-width: 900px; + height: 600px; + padding: 15px; + float: left; +} + +.chart-select-group { + width: 50%; + margin: auto; + position: inherit; + display: block; + vertical-align: middle; +} + +/*.dropdown-menu > li > a {*/ + /*cursor: pointer;*/ +/*}*/ diff --git a/static/src/app/statistic/war-detail-fraction/war-detail-fraction.component.html b/static/src/app/statistic/war-detail-fraction/war-detail-fraction.component.html new file mode 100644 index 0000000..82719c5 --- /dev/null +++ b/static/src/app/statistic/war-detail-fraction/war-detail-fraction.component.html @@ -0,0 +1,74 @@ + + + + + + + + + + + + + + + + + + + +
+
+ + + + + + + + +
+ +
+ + +
+ +
+ + +
+
diff --git a/static/src/app/statistic/war-detail-fraction/war-detail-fraction.component.ts b/static/src/app/statistic/war-detail-fraction/war-detail-fraction.component.ts new file mode 100644 index 0000000..cec9da3 --- /dev/null +++ b/static/src/app/statistic/war-detail-fraction/war-detail-fraction.component.ts @@ -0,0 +1,344 @@ +import {Component, ElementRef, SimpleChanges, ViewChild} from "@angular/core"; +import {LogsService} from "../../services/logs/logs.service"; +import * as d3 from "d3"; +import {ChartUtils} from "../../utils/chart-utils"; +import {Fraction} from "../../utils/fraction.enum"; +import {War} from "../../models/model-interfaces"; + + +@Component({ + selector: 'war-detail-fraction', + templateUrl: './war-detail-fraction.component.html', + inputs: ['war'], + styleUrls: ['./war-detail-fraction.component.css', '../../style/list-entry.css', '../../style/hide-scrollbar.css'] +}) +export class WarDetailFractionComponent { + + readonly fraction = Fraction; + + @ViewChild('overview') private overviewContainer: ElementRef; + + war: War; + + logData: any; + + startDateObj: Date; + + initialized: any; + + public chartSelectModel: string; + + lineChartData: any[] = []; + areaChartData: any[] = []; + + tmpPointData; + tmpBudgetData; + tmpKillData; + tmpFrienlyFireData; + tmpTransportData; + tmpReviveData; + tmpStabilizeData; + tmpFlagCaptureData; + + colorScheme = { + domain: [Fraction.COLOR_BLUFOR, Fraction.COLOR_OPFOR] + }; + + labelPoints = 'Punkte'; + labelBudget = 'Budget'; + labelKill = 'Kills'; + labelFriendlyFire = 'FriendlyFire'; + labelTransport = 'Lufttransport'; + labelRevive = 'Revive'; + labelStabilize = 'Stabilisiert'; + labelFlag = 'Flaggenbesitz'; + lineChartLabel: string = this.labelPoints; + + showLineChart = true; + stepCurve = d3.curveStepAfter; + gradient = false; + yAxis = true; + xAxis = true; + legend = false; + legendTitle = false; + showXAxisLabel = false; + showYAxisLabel = true; + autoscale = true; + timeline = false; + roundDomains = true; + + constructor(private logsService: LogsService) { + } + + ngOnInit() { + } + + ngOnChanges(changes: SimpleChanges) { + if (changes.war) { + this.initialized = { + budget: false, + kill: false, + revive: false, + transport: false, + flag: false + }; + Object.assign(this, [this.lineChartData, this.areaChartData]); + this.chartSelectModel = this.labelPoints; + + this.startDateObj = new Date(this.war.date); + this.startDateObj.setHours(0); + this.startDateObj.setMinutes(1); + this.loadFractionData(); + } + } + + selectChart() { + if (this.chartSelectModel !== this.labelFlag) { + this.showLineChart = true; + this.lineChartLabel = this.chartSelectModel; + switch (this.chartSelectModel) { + case this.labelPoints: + this.lineChartData = this.tmpPointData; + break; + case this.labelBudget: + this.initBudgetData(); + this.lineChartData = this.tmpBudgetData; + break; + case this.labelKill: + this.initKillData(); + this.lineChartData = this.tmpKillData; + break; + case this.labelFriendlyFire: + this.initKillData(); + this.lineChartData = this.tmpFrienlyFireData; + break; + case this.labelRevive: + this.initRevive(); + this.lineChartData = this.tmpReviveData; + break; + case this.labelStabilize: + this.initRevive(); + this.lineChartData = this.tmpStabilizeData; + break; + case this.labelTransport: + this.initTransportData(); + this.lineChartData = this.tmpTransportData; + break; + } + } else { + this.initFlagHoldData(); + this.showLineChart = false; + this.areaChartData = this.tmpFlagCaptureData; + } + } + + loadFractionData() { + this.initializeTempCollections(); + + this.logsService.getFullLog(this.war._id).subscribe((data) => { + this.logData = data; + this.initPointData(); + this.showLineChart = true; + this.lineChartLabel = this.labelPoints; + this.lineChartData = this.tmpPointData; + }); + } + + initPointData() { + this.logData.points.forEach(pointEntry => { + this.tmpPointData[0].series.push(ChartUtils.getSeriesEntry(new Date(pointEntry.time), pointEntry.ptBlufor)); + this.tmpPointData[1].series.push(ChartUtils.getSeriesEntry(new Date(pointEntry.time), pointEntry.ptOpfor)); + }); + this.addFinalTimeData(this.tmpPointData); + } + + initBudgetData() { + if (this.initialized.budget) { + return; + } + this.logData.budget.forEach(budgetEntry => { + const budgetEntryDate = new Date(budgetEntry.time); + const fractionChange = budgetEntry.fraction === 'BLUFOR' ? 0 : 1; + const fractionOld = budgetEntry.fraction !== 'BLUFOR' ? 0 : 1; + + if (this.isTwoMinutesAhead(budgetEntryDate, this.tmpBudgetData)) { + this.tmpBudgetData[fractionChange].series.push(ChartUtils.getSeriesEntry(new Date(budgetEntry.time), budgetEntry.newBudget)); + this.tmpBudgetData[fractionOld].series.push(ChartUtils.getSeriesEntry(new Date(budgetEntry.time), + this.tmpBudgetData[fractionOld].series[this.tmpBudgetData[fractionOld].series.length - 1].value)); + } + }); + this.addFinalTimeData(this.tmpBudgetData); + this.initialized.budget = true; + } + + initKillData() { + if (this.initialized.kill) { + return; + } + let killCountBlufor = 0, killCountOpfor = 0, ffKillCountBlufor = 0, ffKillCountOpfor = 0; + + for (const {killEntry, index} of this.logData.kill.map((killEntry, index) => ({killEntry, index}))) { + const killEntryDate = new Date(killEntry.time); + if (killEntry.friendlyFire === false) { + if (killEntry.fraction === 'BLUFOR') { + killCountBlufor++; + } + if (killEntry.fraction === 'OPFOR') { + killCountOpfor++; + } + if (this.isTwoMinutesAhead(killEntryDate, this.tmpKillData)) { + this.tmpKillData[0].series.push(ChartUtils.getSeriesEntry(killEntryDate, killCountBlufor)); + this.tmpKillData[1].series.push(ChartUtils.getSeriesEntry(killEntryDate, killCountOpfor)); + } + } else { + if (killEntry.fraction === 'BLUFOR') { + ffKillCountBlufor++; + } + if (killEntry.fraction === 'OPFOR') { + ffKillCountOpfor++; + } + if (this.isTwoMinutesAhead(killEntryDate, this.tmpFrienlyFireData)) { + this.tmpFrienlyFireData[0].series.push(ChartUtils.getSeriesEntry(killEntryDate, ffKillCountBlufor)); + this.tmpFrienlyFireData[1].series.push(ChartUtils.getSeriesEntry(killEntryDate, ffKillCountOpfor)); + } + } + if (index === this.logData.kill.length - 1) { + this.tmpKillData[0].series.push(ChartUtils.getSeriesEntry(killEntryDate, killCountBlufor)); + this.tmpKillData[1].series.push(ChartUtils.getSeriesEntry(killEntryDate, killCountOpfor)); + this.tmpFrienlyFireData[0].series.push(ChartUtils.getSeriesEntry(killEntryDate, ffKillCountBlufor)); + this.tmpFrienlyFireData[1].series.push(ChartUtils.getSeriesEntry(killEntryDate, ffKillCountOpfor)); + } + } + + this.addFinalTimeData(this.tmpKillData); + this.addFinalTimeData(this.tmpFrienlyFireData) + this.initialized.kill = true; + } + + initRevive() { + if (this.initialized.revive) { + return; + } + let reviveCountBlufor = 0, reviveCountOpfor = 0, stabilizeCountBlufor = 0, stabilizeCountOpfor = 0; + for (const {reviveEntry, index} of this.logData.revive.map((reviveEntry, index) => ({reviveEntry, index}))) { + const reviveEntryDate = new Date(reviveEntry.time); + if (reviveEntry.stabilized === false) { + if (reviveEntry.fraction === 'BLUFOR') { + reviveCountBlufor++; + } else { + reviveCountOpfor++; + } + if (this.isTwoMinutesAhead(reviveEntryDate, this.tmpReviveData)) { + this.tmpReviveData[0].series.push(ChartUtils.getSeriesEntry(reviveEntryDate, reviveCountBlufor)); + this.tmpReviveData[1].series.push(ChartUtils.getSeriesEntry(reviveEntryDate, reviveCountOpfor)); + } + } else { + if (reviveEntry.fraction === 'BLUFOR') { + stabilizeCountBlufor++; + } else { + stabilizeCountOpfor++; + } + if (this.isTwoMinutesAhead(reviveEntryDate, this.tmpStabilizeData)) { + this.tmpStabilizeData[0].series.push(ChartUtils.getSeriesEntry(reviveEntryDate, stabilizeCountBlufor)); + this.tmpStabilizeData[1].series.push(ChartUtils.getSeriesEntry(reviveEntryDate, stabilizeCountOpfor)); + } + } + if (index === this.logData.revive.length - 1) { + this.tmpReviveData[0].series.push(ChartUtils.getSeriesEntry(reviveEntryDate, reviveCountBlufor)); + this.tmpReviveData[1].series.push(ChartUtils.getSeriesEntry(reviveEntryDate, reviveCountOpfor)); + this.tmpStabilizeData[0].series.push(ChartUtils.getSeriesEntry(reviveEntryDate, stabilizeCountBlufor)); + this.tmpStabilizeData[1].series.push(ChartUtils.getSeriesEntry(reviveEntryDate, stabilizeCountOpfor)); + } + } + this.addFinalTimeData(this.tmpReviveData); + this.addFinalTimeData(this.tmpStabilizeData); + this.initialized.revive = true; + } + + initTransportData() { + if (this.initialized.transport) { + return; + } + let transportCountBlufor = 0, transportCountOpfor = 0; + for (const {transportEntry, index} of this.logData.transport.map((transportEntry, index) => ({ + transportEntry, + index + }))) { + const transportEntryDate = new Date(transportEntry.time); + if (transportEntry.fraction === 'BLUFOR') { + transportCountBlufor++; + } else { + transportCountOpfor++; + } + if (this.isTwoMinutesAhead(transportEntryDate, this.tmpTransportData) || index === this.logData.transport.length - 1) { + this.tmpTransportData[0].series.push(ChartUtils.getSeriesEntry(transportEntryDate, transportCountBlufor)); + this.tmpTransportData[1].series.push(ChartUtils.getSeriesEntry(transportEntryDate, transportCountOpfor)); + } + } + this.addFinalTimeData(this.tmpTransportData); + this.initialized.transport = true; + + } + + initFlagHoldData() { + if (this.initialized.flag) { + return; + } + let flagStatusBlufor = true; + let flagStatusOpfor = true; + this.tmpFlagCaptureData[0].series.push(ChartUtils.getSeriesEntry(this.startDateObj, flagStatusBlufor)); + this.tmpFlagCaptureData[1].series.push(ChartUtils.getSeriesEntry(this.startDateObj, flagStatusOpfor)); + + this.logData.flag.forEach(flagEntry => { + if (flagEntry.flagFraction === 'BLUFOR') { + flagStatusBlufor = !flagEntry.capture; + } else { + flagStatusOpfor = !flagEntry.capture; + } + this.tmpFlagCaptureData[flagEntry.flagFraction === 'BLUFOR' ? 0 : 1].series.push( + ChartUtils.getSeriesEntry(new Date(flagEntry.time), flagEntry.flagFraction === 'BLUFOR' ? flagStatusBlufor : flagStatusOpfor) + ) + }); + + this.addFinalTimeData(this.tmpFlagCaptureData); + this.initialized.flag = true; + } + + protected isTwoMinutesAhead(entryDate: Date, tmpData: any): boolean { + return entryDate.getTime() >= tmpData[0].series[tmpData[0].series.length - 1].name.getTime() + (1.5 * 60000) + } + + initializeTempCollections() { + this.tmpPointData = ChartUtils.getMultiDataArray(Fraction.BLUFOR, Fraction.OPFOR); + this.tmpBudgetData = ChartUtils.getMultiDataArray(Fraction.BLUFOR, Fraction.OPFOR); + this.tmpKillData = ChartUtils.getMultiDataArray(Fraction.BLUFOR, Fraction.OPFOR); + this.tmpFrienlyFireData = ChartUtils.getMultiDataArray(Fraction.BLUFOR, Fraction.OPFOR); + this.tmpTransportData = ChartUtils.getMultiDataArray(Fraction.BLUFOR, Fraction.OPFOR); + this.tmpReviveData = ChartUtils.getMultiDataArray(Fraction.BLUFOR, Fraction.OPFOR); + this.tmpStabilizeData = ChartUtils.getMultiDataArray(Fraction.BLUFOR, Fraction.OPFOR); + this.tmpFlagCaptureData = ChartUtils.getMultiDataArray(Fraction.BLUFOR, Fraction.OPFOR); + + [this.tmpKillData, this.tmpFrienlyFireData, this.tmpReviveData, this.tmpStabilizeData, this.tmpTransportData].forEach(tmp => { + [0, 1].forEach(index => { + tmp[index].series.push(ChartUtils.getSeriesEntry(this.startDateObj, 0)); + }) + }); + this.tmpBudgetData[0].series.push(ChartUtils.getSeriesEntry(this.startDateObj, this.war.budgetBlufor)); + this.tmpBudgetData[1].series.push(ChartUtils.getSeriesEntry(this.startDateObj, this.war.budgetOpfor)); + } + + addFinalTimeData(tmpCollection) { + const endDate = new Date(this.war.endDate); + if (tmpCollection === this.tmpBudgetData) { + this.tmpBudgetData[0].series.push(ChartUtils.getSeriesEntry(endDate, this.war.endBudgetBlufor)); + this.tmpBudgetData[1].series.push(ChartUtils.getSeriesEntry(endDate, this.war.endBudgetOpfor)); + } else { + for (let j in [0, 1]) { + if (tmpCollection[j].series[tmpCollection[j].series.length - 1].name < endDate) { + tmpCollection[j].series.push(ChartUtils.getSeriesEntry(endDate, tmpCollection[j].series[tmpCollection[j].series.length - 1].value)); + } + } + } + } + +} diff --git a/static/src/app/statistic/war-detail-header/war-detail-header.component.css b/static/src/app/statistic/war-detail-header/war-detail-header.component.css index d727ec1..9273124 100644 --- a/static/src/app/statistic/war-detail-header/war-detail-header.component.css +++ b/static/src/app/statistic/war-detail-header/war-detail-header.component.css @@ -13,3 +13,16 @@ .war-header { border-bottom: thin solid lightgrey; } + +.nav-tabs > li.active > a { + background: #222222; +} + +.nav-tabs > li > a { + background: #4b4b4b; +} + +.nav-link { + cursor: pointer !important; + color: #FFF !important; +} diff --git a/static/src/app/statistic/war-detail-header/war-detail-header.component.html b/static/src/app/statistic/war-detail-header/war-detail-header.component.html index a5c31c3..c0f77ec 100644 --- a/static/src/app/statistic/war-detail-header/war-detail-header.component.html +++ b/static/src/app/statistic/war-detail-header/war-detail-header.component.html @@ -58,9 +58,13 @@ - - + + + + + + + diff --git a/static/src/app/statistic/war-detail/war-detail.component.html b/static/src/app/statistic/war-detail/war-detail.component.html index 3a1b31e..780c37d 100644 --- a/static/src/app/statistic/war-detail/war-detail.component.html +++ b/static/src/app/statistic/war-detail/war-detail.component.html @@ -1,5 +1,4 @@
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
From cb7146446280d8a72da41d99e5e7716ef0bd459b Mon Sep 17 00:00:00 2001 From: HardiReady Date: Mon, 13 Nov 2017 00:06:39 +0100 Subject: [PATCH 3/7] Finish basic modulized war detail components --- static/src/app/app.routing.ts | 16 +-- .../war-detail-fraction.component.css | 101 +----------------- .../war-detail-fraction.component.html | 35 +++--- .../war-detail-header.component.css | 5 + .../war-detail-header.component.html | 25 +++-- .../war-detail-header.component.ts | 3 + .../war-detail/war-detail.component.css | 2 +- .../war-detail/war-detail.component.html | 54 +++++----- 8 files changed, 79 insertions(+), 162 deletions(-) diff --git a/static/src/app/app.routing.ts b/static/src/app/app.routing.ts index 06eecf2..c9ed43c 100644 --- a/static/src/app/app.routing.ts +++ b/static/src/app/app.routing.ts @@ -58,14 +58,14 @@ export const appRoutes: Routes = [ }, /** Redirect Configuration **/ - // { - // path: '404', - // component: NotFoundComponent - // }, - // { - // path: '**', - // redirectTo: '/404' - // } // always configure this last - first matching route gets processed + { + path: '404', + component: NotFoundComponent + }, + { + path: '**', + redirectTo: '/404' + } // always configure this last - first matching route gets processed ]; export const appRouting = RouterModule.forRoot(appRoutes); diff --git a/static/src/app/statistic/war-detail-fraction/war-detail-fraction.component.css b/static/src/app/statistic/war-detail-fraction/war-detail-fraction.component.css index ac69342..eff3b2f 100644 --- a/static/src/app/statistic/war-detail-fraction/war-detail-fraction.component.css +++ b/static/src/app/statistic/war-detail-fraction/war-detail-fraction.component.css @@ -1,97 +1,3 @@ -.vertical-spacer { - height: 205px; - float: left; - width: 4%; -} - -.head-field { - font-size: 24px; - margin-top: 10px; - margin-bottom: 10px; -} - -@media screen and (min-width: 1500px) { - .vertical-spacer { - width: 15%; - } -} - -@media screen and (min-width: 2000px) { - .vertical-spacer { - width: 20%; - } -} - -.overview { - overflow-y: scroll; - overflow-x: hidden; - border-left: thin solid lightgrey; - bottom: 20px; - height: 100vh; -} - -.player-name { - font-weight: bold; -} - -/* ########### TABS ########### */ - -:host /deep/ .nav-tabs { - padding-left: 35% !important; -} - -:host /deep/ .nav-link { - background: #4b4b4b; - color: white; -} - -:host /deep/ .nav-link:hover { - background: #afafaf; - color: #000; -} - -:host /deep/ .nav-tabs > li.active > a { - background: #222222; - color: white; -} - -/* ########### DATATABLE ########### */ - -:host /deep/ .datatable-header { - background: #222222; - font-weight: 700; - border-radius: 10px 10px 0 0; - color: white; -} - -:host /deep/ span.datatable-header-cell-label, :host /deep/ div.datatable-body-cell-label { - padding-left: 8px; -} - -:host /deep/ .ngx-datatable .datatable-header { - /*vertical center alignment*/ - display: table-cell; - vertical-align: middle; -} - -:host /deep/ .ngx-datatable .datatable-body .datatable-body-row > div { - /*vertical alignment*/ - position: relative; - top: 10px; -} - -:host /deep/ .datatable-body-row { - color: #222222; - border-bottom: 1px solid grey; - cursor: pointer; -} - -:host /deep/ .datatable-body-row:hover { - background-color: #f7f7f7; -} - -/* ########### CHART-TAB ######## */ - .btn-dark { background: #4b4b4b; color: #f5f5f5; @@ -117,13 +23,10 @@ } .chart-select-group { - width: 50%; + width: 980px; margin: auto; - position: inherit; - display: block; - vertical-align: middle; } /*.dropdown-menu > li > a {*/ - /*cursor: pointer;*/ +/*cursor: pointer;*/ /*}*/ diff --git a/static/src/app/statistic/war-detail-fraction/war-detail-fraction.component.html b/static/src/app/statistic/war-detail-fraction/war-detail-fraction.component.html index 82719c5..dec5e6c 100644 --- a/static/src/app/statistic/war-detail-fraction/war-detail-fraction.component.html +++ b/static/src/app/statistic/war-detail-fraction/war-detail-fraction.component.html @@ -18,22 +18,25 @@
-
- - - - - - - - +
+
+ + + + + + + + +
diff --git a/static/src/app/statistic/war-detail-header/war-detail-header.component.css b/static/src/app/statistic/war-detail-header/war-detail-header.component.css index 9273124..0d69397 100644 --- a/static/src/app/statistic/war-detail-header/war-detail-header.component.css +++ b/static/src/app/statistic/war-detail-header/war-detail-header.component.css @@ -22,6 +22,11 @@ background: #4b4b4b; } +.nav-tabs > li:not(.active) > a:hover { + background: #afafaf; + color: #f5f5f5; +} + .nav-link { cursor: pointer !important; color: #FFF !important; diff --git a/static/src/app/statistic/war-detail-header/war-detail-header.component.html b/static/src/app/statistic/war-detail-header/war-detail-header.component.html index c0f77ec..372076c 100644 --- a/static/src/app/statistic/war-detail-header/war-detail-header.component.html +++ b/static/src/app/statistic/war-detail-header/war-detail-header.component.html @@ -50,21 +50,24 @@
- - - - - - - +
+ + + + +
diff --git a/static/src/app/statistic/war-detail-header/war-detail-header.component.ts b/static/src/app/statistic/war-detail-header/war-detail-header.component.ts index f17b40c..b87f166 100644 --- a/static/src/app/statistic/war-detail-header/war-detail-header.component.ts +++ b/static/src/app/statistic/war-detail-header/war-detail-header.component.ts @@ -17,6 +17,8 @@ export class WarDetailHeaderComponent { war: War; + tab: number; + fractionFilterSelected: string; playerChart: any[] = []; @@ -35,6 +37,7 @@ export class WarDetailHeaderComponent { .filter(id => id != undefined) .flatMap(id => this.warService.getWar(id)) .subscribe(war => { + this.tab = 0; this.war = war; this.fractionFilterSelected = undefined; this.playerChart = ChartUtils.getSingleDataArray(Fraction.OPFOR, war.playersOpfor, Fraction.BLUFOR, war.playersBlufor); diff --git a/static/src/app/statistic/war-detail/war-detail.component.css b/static/src/app/statistic/war-detail/war-detail.component.css index 5716be4..96409fd 100644 --- a/static/src/app/statistic/war-detail/war-detail.component.css +++ b/static/src/app/statistic/war-detail/war-detail.component.css @@ -104,5 +104,5 @@ } /*.dropdown-menu > li > a {*/ - /*cursor: pointer;*/ +/*cursor: pointer;*/ /*}*/ diff --git a/static/src/app/statistic/war-detail/war-detail.component.html b/static/src/app/statistic/war-detail/war-detail.component.html index 780c37d..335fb77 100644 --- a/static/src/app/statistic/war-detail/war-detail.component.html +++ b/static/src/app/statistic/war-detail/war-detail.component.html @@ -1,33 +1,33 @@
- - - + + + {{value}} - - - - - {{value === 'BLUFOR' ? fraction.BLUFOR : fraction.OPFOR}} - - - - - - - - - + + + + + {{value === 'BLUFOR' ? fraction.BLUFOR : fraction.OPFOR}} + + + + + + + + +
From a74f1bd6738c0cff547d23eefde802efe7550ce4 Mon Sep 17 00:00:00 2001 From: HardiReady Date: Mon, 13 Nov 2017 13:49:47 +0100 Subject: [PATCH 4/7] Refactor war detail components; Fix styles; Add Scoreboard additional btns --- .../campaign-player-detail.component.html | 2 +- static/src/app/statistic/stats.module.ts | 4 +- static/src/app/statistic/stats.routing.ts | 12 +- .../war-detail-header.component.css | 33 ------ .../war-detail-header.component.html | 73 ------------ .../war-detail-header.component.ts | 52 --------- .../fraction-stats.component.css} | 0 .../fraction-stats.component.html} | 0 .../fraction-stats.component.ts} | 31 +++-- .../scoreboard/scoreboard.component.css | 42 +++++++ .../scoreboard/scoreboard.component.html | 42 +++++++ .../scoreboard/scoreboard.component.ts | 72 ++++++++++++ .../war-detail/war-detail.component.css | 99 +++------------- .../war-detail/war-detail.component.html | 106 ++++++++++++------ .../war-detail/war-detail.component.ts | 80 +++++++------ 15 files changed, 304 insertions(+), 344 deletions(-) delete mode 100644 static/src/app/statistic/war-detail-header/war-detail-header.component.css delete mode 100644 static/src/app/statistic/war-detail-header/war-detail-header.component.html delete mode 100644 static/src/app/statistic/war-detail-header/war-detail-header.component.ts rename static/src/app/statistic/{war-detail-fraction/war-detail-fraction.component.css => war-detail/fraction-stats/fraction-stats.component.css} (100%) rename static/src/app/statistic/{war-detail-fraction/war-detail-fraction.component.html => war-detail/fraction-stats/fraction-stats.component.html} (100%) rename static/src/app/statistic/{war-detail-fraction/war-detail-fraction.component.ts => war-detail/fraction-stats/fraction-stats.component.ts} (93%) create mode 100644 static/src/app/statistic/war-detail/scoreboard/scoreboard.component.css create mode 100644 static/src/app/statistic/war-detail/scoreboard/scoreboard.component.html create mode 100644 static/src/app/statistic/war-detail/scoreboard/scoreboard.component.ts diff --git a/static/src/app/statistic/campaign-player-detail/campaign-player-detail.component.html b/static/src/app/statistic/campaign-player-detail/campaign-player-detail.component.html index 8507339..d9a92f9 100644 --- a/static/src/app/statistic/campaign-player-detail/campaign-player-detail.component.html +++ b/static/src/app/statistic/campaign-player-detail/campaign-player-detail.component.html @@ -1,5 +1,5 @@
-

Spielerstatistik - {{campaignPlayer.name}}

+

Kampagnendetails - {{campaignPlayer.name}}

{{campaignPlayer.campaign.title}} Kampagne

< Zurück diff --git a/static/src/app/statistic/stats.module.ts b/static/src/app/statistic/stats.module.ts index 5be86ae..27c7bb5 100644 --- a/static/src/app/statistic/stats.module.ts +++ b/static/src/app/statistic/stats.module.ts @@ -4,7 +4,7 @@ import {SharedModule} from "../shared.module"; import {statsRouterModule, statsRoutingComponents} from "./stats.routing"; import {WarService} from "../services/logs/war.service"; import {NgxChartsModule} from "@swimlane/ngx-charts"; -import {AccordionModule, BsDropdownModule, ButtonsModule, TabsModule} from "ngx-bootstrap"; +import {AccordionModule, ButtonsModule} from "ngx-bootstrap"; import {CampaignService} from "../services/logs/campaign.service"; import {NgxDatatableModule} from "@swimlane/ngx-datatable"; import {PlayerService} from "../services/logs/player.service"; @@ -13,7 +13,7 @@ import {LogsService} from "../services/logs/logs.service"; @NgModule({ declarations: statsRoutingComponents, imports: [CommonModule, SharedModule, statsRouterModule, NgxChartsModule, - AccordionModule.forRoot(), BsDropdownModule.forRoot(), ButtonsModule.forRoot(), TabsModule.forRoot(), NgxDatatableModule], + AccordionModule.forRoot(), ButtonsModule.forRoot(), NgxDatatableModule], providers: [WarService, CampaignService, PlayerService, LogsService] }) export class StatsModule { diff --git a/static/src/app/statistic/stats.routing.ts b/static/src/app/statistic/stats.routing.ts index 92b1188..db263b9 100644 --- a/static/src/app/statistic/stats.routing.ts +++ b/static/src/app/statistic/stats.routing.ts @@ -1,15 +1,15 @@ import {RouterModule, Routes} from "@angular/router"; import {StatisticComponent} from "./stats.component"; -import {WarDetailComponent} from "./war-detail/war-detail.component"; -import {WarSubmitComponent} from "./war-submit/war-submit.component"; import {WarListComponent} from "./war-list/war-list.component"; import {StatisticOverviewComponent} from "./overview/stats-overview.component"; import {WarItemComponent} from "./war-list/war-item.component"; import {ModuleWithProviders} from "@angular/core"; import {CampaignSubmitComponent} from "./campaign-submit/campaign-submit.component"; import {CampaignPlayerDetailComponent} from "./campaign-player-detail/campaign-player-detail.component"; -import {WarDetailHeaderComponent} from "./war-detail-header/war-detail-header.component"; -import {WarDetailFractionComponent} from "./war-detail-fraction/war-detail-fraction.component"; +import {WarDetailComponent} from "./war-detail/war-detail.component"; +import {ScoreboardComponent} from "./war-detail/scoreboard/scoreboard.component"; +import {WarSubmitComponent} from "./war-submit/war-submit.component"; +import {FractionStatsComponent} from "./war-detail/fraction-stats/fraction-stats.component"; export const statsRoutes: Routes = [{ @@ -38,7 +38,7 @@ export const statsRoutes: Routes = [{ }, { path: 'war/:id', - component: WarDetailHeaderComponent, + component: WarDetailComponent, outlet: 'right' }, { @@ -50,6 +50,6 @@ export const statsRoutes: Routes = [{ export const statsRouterModule: ModuleWithProviders = RouterModule.forChild(statsRoutes); export const statsRoutingComponents = [StatisticComponent, StatisticOverviewComponent, CampaignSubmitComponent, - WarListComponent, WarSubmitComponent, WarDetailHeaderComponent, WarDetailComponent, WarDetailFractionComponent, + WarListComponent, WarSubmitComponent, WarDetailComponent, ScoreboardComponent, FractionStatsComponent, CampaignPlayerDetailComponent, WarItemComponent]; diff --git a/static/src/app/statistic/war-detail-header/war-detail-header.component.css b/static/src/app/statistic/war-detail-header/war-detail-header.component.css deleted file mode 100644 index 0d69397..0000000 --- a/static/src/app/statistic/war-detail-header/war-detail-header.component.css +++ /dev/null @@ -1,33 +0,0 @@ -.war-header-container { - width: 920px; - min-height: 205px; - margin: auto; -} - -.head-field { - font-size: 24px; - margin-top: 10px; - margin-bottom: 10px; -} - -.war-header { - border-bottom: thin solid lightgrey; -} - -.nav-tabs > li.active > a { - background: #222222; -} - -.nav-tabs > li > a { - background: #4b4b4b; -} - -.nav-tabs > li:not(.active) > a:hover { - background: #afafaf; - color: #f5f5f5; -} - -.nav-link { - cursor: pointer !important; - color: #FFF !important; -} diff --git a/static/src/app/statistic/war-detail-header/war-detail-header.component.html b/static/src/app/statistic/war-detail-header/war-detail-header.component.html deleted file mode 100644 index 372076c..0000000 --- a/static/src/app/statistic/war-detail-header/war-detail-header.component.html +++ /dev/null @@ -1,73 +0,0 @@ -
-
-

{{war.title}} - vom {{war.date | date: 'dd.MM.yyyy'}}

-
-

Endpunktestand:

- {{fraction.BLUFOR}} {{war.ptBlufor}} - | - {{war.ptOpfor}} {{fraction.OPFOR}} -
- -
-

Teilnehmer:

- - -
- -
- Logfile - anzeigen -
- - - -
-
-
-
- - - -
- - - - -
- -
diff --git a/static/src/app/statistic/war-detail-header/war-detail-header.component.ts b/static/src/app/statistic/war-detail-header/war-detail-header.component.ts deleted file mode 100644 index b87f166..0000000 --- a/static/src/app/statistic/war-detail-header/war-detail-header.component.ts +++ /dev/null @@ -1,52 +0,0 @@ -import {Component} from "@angular/core"; -import {ActivatedRoute} from "@angular/router"; -import {WarService} from "../../services/logs/war.service"; -import {War} from "../../models/model-interfaces"; -import {ChartUtils} from "../../utils/chart-utils"; -import {Fraction} from "../../utils/fraction.enum"; - - -@Component({ - selector: 'war-detail-header', - templateUrl: './war-detail-header.component.html', - styleUrls: ['./war-detail-header.component.css', '../../style/list-entry.css', '../../style/hide-scrollbar.css'] -}) -export class WarDetailHeaderComponent { - - readonly fraction = Fraction; - - war: War; - - tab: number; - - fractionFilterSelected: string; - - playerChart: any[] = []; - - colorScheme = { - domain: [Fraction.COLOR_OPFOR, Fraction.COLOR_BLUFOR] - }; - - constructor(private route: ActivatedRoute, - private warService: WarService) { - } - - ngOnInit() { - this.route.params - .map(params => params['id']) - .filter(id => id != undefined) - .flatMap(id => this.warService.getWar(id)) - .subscribe(war => { - this.tab = 0; - this.war = war; - this.fractionFilterSelected = undefined; - this.playerChart = ChartUtils.getSingleDataArray(Fraction.OPFOR, war.playersOpfor, Fraction.BLUFOR, war.playersBlufor); - Object.assign(this, [this.playerChart]); - }) - } - - filterPlayersByFraction(fraction?: string) { - this.fractionFilterSelected = fraction; - } - -} diff --git a/static/src/app/statistic/war-detail-fraction/war-detail-fraction.component.css b/static/src/app/statistic/war-detail/fraction-stats/fraction-stats.component.css similarity index 100% rename from static/src/app/statistic/war-detail-fraction/war-detail-fraction.component.css rename to static/src/app/statistic/war-detail/fraction-stats/fraction-stats.component.css diff --git a/static/src/app/statistic/war-detail-fraction/war-detail-fraction.component.html b/static/src/app/statistic/war-detail/fraction-stats/fraction-stats.component.html similarity index 100% rename from static/src/app/statistic/war-detail-fraction/war-detail-fraction.component.html rename to static/src/app/statistic/war-detail/fraction-stats/fraction-stats.component.html diff --git a/static/src/app/statistic/war-detail-fraction/war-detail-fraction.component.ts b/static/src/app/statistic/war-detail/fraction-stats/fraction-stats.component.ts similarity index 93% rename from static/src/app/statistic/war-detail-fraction/war-detail-fraction.component.ts rename to static/src/app/statistic/war-detail/fraction-stats/fraction-stats.component.ts index cec9da3..58756a7 100644 --- a/static/src/app/statistic/war-detail-fraction/war-detail-fraction.component.ts +++ b/static/src/app/statistic/war-detail/fraction-stats/fraction-stats.component.ts @@ -1,18 +1,17 @@ import {Component, ElementRef, SimpleChanges, ViewChild} from "@angular/core"; -import {LogsService} from "../../services/logs/logs.service"; import * as d3 from "d3"; -import {ChartUtils} from "../../utils/chart-utils"; -import {Fraction} from "../../utils/fraction.enum"; -import {War} from "../../models/model-interfaces"; +import {ChartUtils} from "../../../utils/chart-utils"; +import {Fraction} from "../../../utils/fraction.enum"; +import {War} from "../../../models/model-interfaces"; @Component({ selector: 'war-detail-fraction', - templateUrl: './war-detail-fraction.component.html', - inputs: ['war'], - styleUrls: ['./war-detail-fraction.component.css', '../../style/list-entry.css', '../../style/hide-scrollbar.css'] + templateUrl: './fraction-stats.component.html', + inputs: ['war', 'logData'], + styleUrls: ['./fraction-stats.component.css', '../../../style/list-entry.css', '../../../style/hide-scrollbar.css'] }) -export class WarDetailFractionComponent { +export class FractionStatsComponent { readonly fraction = Fraction; @@ -67,14 +66,14 @@ export class WarDetailFractionComponent { timeline = false; roundDomains = true; - constructor(private logsService: LogsService) { + constructor() { } ngOnInit() { } ngOnChanges(changes: SimpleChanges) { - if (changes.war) { + if (changes.war || changes.logData) { this.initialized = { budget: false, kill: false, @@ -134,14 +133,10 @@ export class WarDetailFractionComponent { loadFractionData() { this.initializeTempCollections(); - - this.logsService.getFullLog(this.war._id).subscribe((data) => { - this.logData = data; - this.initPointData(); - this.showLineChart = true; - this.lineChartLabel = this.labelPoints; - this.lineChartData = this.tmpPointData; - }); + this.initPointData(); + this.showLineChart = true; + this.lineChartLabel = this.labelPoints; + this.lineChartData = this.tmpPointData; } initPointData() { diff --git a/static/src/app/statistic/war-detail/scoreboard/scoreboard.component.css b/static/src/app/statistic/war-detail/scoreboard/scoreboard.component.css new file mode 100644 index 0000000..856b24a --- /dev/null +++ b/static/src/app/statistic/war-detail/scoreboard/scoreboard.component.css @@ -0,0 +1,42 @@ +.player-name { + font-weight: bold; +} + +/* ########### DATATABLE ########### */ + +:host /deep/ .datatable-header { + background: #222222; + font-weight: 700; + border-radius: 10px 10px 0 0; + color: white; +} + +:host /deep/ span.datatable-header-cell-label, :host /deep/ div.datatable-body-cell-label { + padding-left: 8px; +} + +:host /deep/ .ngx-datatable .datatable-header { + /*vertical center alignment*/ + display: table-cell; + vertical-align: middle; +} + +:host /deep/ .ngx-datatable .datatable-body .datatable-body-row > div { + /*vertical alignment*/ + position: relative; + top: 10px; +} + +:host /deep/ .datatable-body-row { + color: #222222; + border-bottom: 1px solid grey; +} + +:host /deep/ .datatable-body-row:hover { + background-color: #f7f7f7; +} + +.in-table-btn { + position: absolute; + margin-top: -5px; +} diff --git a/static/src/app/statistic/war-detail/scoreboard/scoreboard.component.html b/static/src/app/statistic/war-detail/scoreboard/scoreboard.component.html new file mode 100644 index 0000000..cb70ec2 --- /dev/null +++ b/static/src/app/statistic/war-detail/scoreboard/scoreboard.component.html @@ -0,0 +1,42 @@ +
+ + + + + {{value}} + + + + + + {{value === 'BLUFOR' ? fraction.BLUFOR : fraction.OPFOR}} + + + + + + + + + + + Detail + + + + + Gesamt + + + +
diff --git a/static/src/app/statistic/war-detail/scoreboard/scoreboard.component.ts b/static/src/app/statistic/war-detail/scoreboard/scoreboard.component.ts new file mode 100644 index 0000000..945fbbe --- /dev/null +++ b/static/src/app/statistic/war-detail/scoreboard/scoreboard.component.ts @@ -0,0 +1,72 @@ +import {Component, ElementRef, SimpleChanges, ViewChild} from "@angular/core"; +import {ActivatedRoute, Router} from "@angular/router"; +import {War} from "../../../models/model-interfaces"; +import {Fraction} from "../../../utils/fraction.enum"; + +@Component({ + selector: 'scoreboard', + templateUrl: './scoreboard.component.html', + inputs: ['war', 'fractionFilterSelected'], + styleUrls: ['./scoreboard.component.css', '../../../style/list-entry.css', '../../../style/hide-scrollbar.css'] +}) +export class ScoreboardComponent { + + readonly fraction = Fraction; + + @ViewChild('overview') private overviewContainer: ElementRef; + + war: War; + + fractionFilterSelected: string; + + cellHeight = 40; + + rows = []; + + reorderable: boolean = false; + + customClasses = { + sortAscending: 'glyphicon glyphicon-triangle-top', + sortDescending: 'glyphicon glyphicon-triangle-bottom', + }; + + constructor(private route: ActivatedRoute, + private router: Router) { + } + + ngOnInit() { + } + + selectPlayerDetail(playerName: string) { + this.router.navigate(['../../campaign-player/' + this.war.campaign + '/' + playerName], + {relativeTo: this.route}); + } + + ngOnChanges(changes: SimpleChanges) { + if (changes.war) { + this.rows = changes.war.currentValue.players; + } + if (changes.fractionFilterSelected) { + this.filterPlayersByFraction(this.fractionFilterSelected) + } + this.scrollOverviewTop(); + } + + scrollOverviewTop() { + try { + this.overviewContainer.nativeElement.scrollTop = 0; + } catch (err) { + } + } + + filterPlayersByFraction(fraction?: string) { + if (fraction) { + this.rows = this.war.players.filter((player) => { + return player.fraction === fraction; + }) + } else { + this.rows = this.war.players; + } + } + +} diff --git a/static/src/app/statistic/war-detail/war-detail.component.css b/static/src/app/statistic/war-detail/war-detail.component.css index 96409fd..fc05931 100644 --- a/static/src/app/statistic/war-detail/war-detail.component.css +++ b/static/src/app/statistic/war-detail/war-detail.component.css @@ -1,7 +1,7 @@ -.vertical-spacer { - height: 205px; - float: left; - width: 4%; +.war-header-container { + width: 920px; + min-height: 205px; + margin: auto; } .head-field { @@ -10,99 +10,28 @@ margin-bottom: 10px; } -@media screen and (min-width: 1500px) { - .vertical-spacer { - width: 15%; - } +.war-header { + border-bottom: thin solid lightgrey; } -@media screen and (min-width: 2000px) { - .vertical-spacer { - width: 20%; - } -} - -.overview { - overflow-y: scroll; - overflow-x: hidden; - border-left: thin solid lightgrey; - bottom: 20px; - height: 100vh; -} - -.player-name { - font-weight: bold; -} - -/* ########### DATATABLE ########### */ - -:host /deep/ .datatable-header { +.nav-tabs > li.active > a { background: #222222; - font-weight: 700; - border-radius: 10px 10px 0 0; - color: white; } -:host /deep/ span.datatable-header-cell-label, :host /deep/ div.datatable-body-cell-label { - padding-left: 8px; +.nav-tabs { + border-bottom: 0; } -:host /deep/ .ngx-datatable .datatable-header { - /*vertical center alignment*/ - display: table-cell; - vertical-align: middle; -} - -:host /deep/ .ngx-datatable .datatable-body .datatable-body-row > div { - /*vertical alignment*/ - position: relative; - top: 10px; -} - -:host /deep/ .datatable-body-row { - color: #222222; - border-bottom: 1px solid grey; - cursor: pointer; -} - -:host /deep/ .datatable-body-row:hover { - background-color: #f7f7f7; -} - -/* ########### CHART-TAB ######## */ - -.btn-dark { +.nav-tabs > li > a { background: #4b4b4b; - color: #f5f5f5; - border-color: #000; } -.btn-dark:hover { +.nav-tabs > li:not(.active) > a:hover { background: #afafaf; color: #f5f5f5; } -.btn-dark.active { - background: #222222; +.nav-link { + cursor: pointer !important; + color: #FFF !important; } - -.chart-container { - width: 95%; - margin: 2%; - min-width: 900px; - height: 600px; - padding: 15px; - float: left; -} - -.chart-select-group { - width: 50%; - margin: auto; - position: inherit; - display: block; - vertical-align: middle; -} - -/*.dropdown-menu > li > a {*/ -/*cursor: pointer;*/ -/*}*/ diff --git a/static/src/app/statistic/war-detail/war-detail.component.html b/static/src/app/statistic/war-detail/war-detail.component.html index 335fb77..6efb2b7 100644 --- a/static/src/app/statistic/war-detail/war-detail.component.html +++ b/static/src/app/statistic/war-detail/war-detail.component.html @@ -1,33 +1,75 @@ -
- - - - - {{value}} - - - - - - {{value === 'BLUFOR' ? fraction.BLUFOR : fraction.OPFOR}} - - - - - - - - - +
+
+

{{war.title}} - vom {{war.date | date: 'dd.MM.yyyy'}}

+
+

Endpunktestand:

+ {{fraction.BLUFOR}} {{war.ptBlufor}} + | + {{war.ptOpfor}} {{fraction.OPFOR}} +
+ +
+

Teilnehmer:

+ + +
+ +
+ Logfile + anzeigen +
+ + + +
+
+
+
+ + + + +
+ + + + +
+
diff --git a/static/src/app/statistic/war-detail/war-detail.component.ts b/static/src/app/statistic/war-detail/war-detail.component.ts index cdea6c5..5560a9e 100644 --- a/static/src/app/statistic/war-detail/war-detail.component.ts +++ b/static/src/app/statistic/war-detail/war-detail.component.ts @@ -1,75 +1,71 @@ -import {Component, ElementRef, SimpleChanges, ViewChild} from "@angular/core"; -import {ActivatedRoute, Router} from "@angular/router"; +import {Component} from "@angular/core"; +import {ActivatedRoute} from "@angular/router"; +import {WarService} from "../../services/logs/war.service"; import {War} from "../../models/model-interfaces"; +import {ChartUtils} from "../../utils/chart-utils"; import {Fraction} from "../../utils/fraction.enum"; +import {LogsService} from "../../services/logs/logs.service"; @Component({ selector: 'war-detail', templateUrl: './war-detail.component.html', - inputs: ['war', 'fractionFilterSelected'], styleUrls: ['./war-detail.component.css', '../../style/list-entry.css', '../../style/hide-scrollbar.css'] }) export class WarDetailComponent { readonly fraction = Fraction; - @ViewChild('overview') private overviewContainer: ElementRef; - war: War; + logData; + + tab: number; + + fractionStatsInitialized: boolean; + fractionFilterSelected: string; - cellHeight = 40; + playerChart: any[] = []; - rows = []; - - reorderable: boolean = false; - - customClasses = { - sortAscending: 'glyphicon glyphicon-triangle-top', - sortDescending: 'glyphicon glyphicon-triangle-bottom', + colorScheme = { + domain: [Fraction.COLOR_OPFOR, Fraction.COLOR_BLUFOR] }; constructor(private route: ActivatedRoute, - private router: Router) { + private warService: WarService, + private logsService: LogsService) { } ngOnInit() { + this.route.params + .map(params => params['id']) + .filter(id => id != undefined) + .flatMap(id => this.warService.getWar(id)) + .subscribe(war => { + this.war = war; + + this.tab = 0; + this.fractionStatsInitialized = false; + this.fractionFilterSelected = undefined; + + this.playerChart = ChartUtils.getSingleDataArray(Fraction.OPFOR, war.playersOpfor, Fraction.BLUFOR, war.playersBlufor); + Object.assign(this, [this.playerChart]); + }) } - selectPlayerDetail(player) { - if (player && player.selected && player.selected.length > 0) { - this.router.navigate(['../../campaign-player/' + this.war.campaign + '/' + player.selected[0].name], - {relativeTo: this.route}); - } - } - - ngOnChanges(changes: SimpleChanges) { - if (changes.war) { - this.rows = changes.war.currentValue.players; - } - if (changes.fractionFilterSelected) { - this.filterPlayersByFraction(this.fractionFilterSelected) - } - this.scrollOverviewTop(); - } - - scrollOverviewTop() { - try { - this.overviewContainer.nativeElement.scrollTop = 0; - } catch (err) { + switchTab(index: number) { + this.tab = index; + if (index === 1 && !this.fractionStatsInitialized) { + this.logsService.getFullLog(this.war._id).subscribe(log => { + this.logData = log; + this.fractionStatsInitialized = true; + }); } } filterPlayersByFraction(fraction?: string) { - if (fraction) { - this.rows = this.war.players.filter((player) => { - return player.fraction === fraction; - }) - } else { - this.rows = this.war.players; - } + this.fractionFilterSelected = fraction; } } From 2747ea41c6f30230c74b494998ace203fc13b04e Mon Sep 17 00:00:00 2001 From: HardiReady Date: Mon, 13 Nov 2017 14:00:59 +0100 Subject: [PATCH 5/7] Add player tab btn --- static/src/app/statistic/war-detail/war-detail.component.css | 4 ++++ static/src/app/statistic/war-detail/war-detail.component.html | 3 +++ 2 files changed, 7 insertions(+) diff --git a/static/src/app/statistic/war-detail/war-detail.component.css b/static/src/app/statistic/war-detail/war-detail.component.css index fc05931..11f1770 100644 --- a/static/src/app/statistic/war-detail/war-detail.component.css +++ b/static/src/app/statistic/war-detail/war-detail.component.css @@ -35,3 +35,7 @@ cursor: pointer !important; color: #FFF !important; } + +.nav-tabs > li.deactivated > a.nav-link{ + cursor: not-allowed!important; +} diff --git a/static/src/app/statistic/war-detail/war-detail.component.html b/static/src/app/statistic/war-detail/war-detail.component.html index 6efb2b7..44e04a0 100644 --- a/static/src/app/statistic/war-detail/war-detail.component.html +++ b/static/src/app/statistic/war-detail/war-detail.component.html @@ -56,6 +56,9 @@ + From eeb166f0e9e00fd5a3f20b7fb758165c71fa00a8 Mon Sep 17 00:00:00 2001 From: HardiReady Date: Mon, 13 Nov 2017 15:45:12 +0100 Subject: [PATCH 6/7] Add campaign player detail as tab --- .../campaign-player-detail.component.css | 5 ++++ .../campaign-player-detail.component.html | 3 +- .../campaign-player-detail.component.ts | 30 +++++++++---------- .../scoreboard/scoreboard.component.html | 4 +-- .../scoreboard/scoreboard.component.ts | 22 ++++---------- .../war-detail/war-detail.component.css | 4 +-- .../war-detail/war-detail.component.html | 9 +++++- .../war-detail/war-detail.component.ts | 17 ++++++++++- .../users/user-list/user-list.component.html | 2 +- static/src/main.ts | 23 -------------- 10 files changed, 55 insertions(+), 64 deletions(-) diff --git a/static/src/app/statistic/campaign-player-detail/campaign-player-detail.component.css b/static/src/app/statistic/campaign-player-detail/campaign-player-detail.component.css index a525771..58a0d9c 100644 --- a/static/src/app/statistic/campaign-player-detail/campaign-player-detail.component.css +++ b/static/src/app/statistic/campaign-player-detail/campaign-player-detail.component.css @@ -1,3 +1,8 @@ +.player-campaign-detail-container { + padding: 0 1% 0 1%; + border-top: thin solid lightgrey; +} + h2 { padding: 10px; } diff --git a/static/src/app/statistic/campaign-player-detail/campaign-player-detail.component.html b/static/src/app/statistic/campaign-player-detail/campaign-player-detail.component.html index d9a92f9..3f0e0e8 100644 --- a/static/src/app/statistic/campaign-player-detail/campaign-player-detail.component.html +++ b/static/src/app/statistic/campaign-player-detail/campaign-player-detail.component.html @@ -1,10 +1,9 @@ -
+

Kampagnendetails - {{campaignPlayer.name}}

{{campaignPlayer.campaign.title}} Kampagne

< Zurück -
[params['id'], params['playerName']]) - .flatMap(id => this.playerService.getCampaignPlayer(id[0], encodeURIComponent(id[1]))) + this.playerService.getCampaignPlayer(this.campaignId, encodeURIComponent(this.playerName)) .subscribe(campaignPlayer => { this.campaignPlayer = campaignPlayer; this.killData = this.assignData(this.yAxisKill, "kill"); @@ -91,14 +93,10 @@ export class CampaignPlayerDetailComponent { this.reviveData = this.assignData(this.yAxisRevive, "revive"); this.captureData = this.assignData(this.yAxisCapture, "flagTouch"); - if (this.totalDeath === 0) { - // avoid infinite or NaN with no death - this.totalDeath = 1; - } - this.kdRatio = parseFloat((this.totalKills / this.totalDeath).toFixed(2)); + this.kdRatio = parseFloat((this.totalKills / (this.totalDeath === 0 ? 1 : this.totalDeath)).toFixed(2)); if (this.kdRatio > 1) this.maxKd = this.kdRatio * 1.7; - this.respawnDeathRatio = parseFloat((this.totalRespawn / this.totalDeath).toFixed(2)); + this.respawnDeathRatio = parseFloat((this.totalRespawn / (this.totalDeath === 0 ? 1 : this.totalDeath)).toFixed(2)); this.sumData = [ { @@ -177,7 +175,7 @@ export class CampaignPlayerDetailComponent { } navigateBack() { - this.location.back(); + this.switchTab.emit(0); } } diff --git a/static/src/app/statistic/war-detail/scoreboard/scoreboard.component.html b/static/src/app/statistic/war-detail/scoreboard/scoreboard.component.html index cb70ec2..4b0020e 100644 --- a/static/src/app/statistic/war-detail/scoreboard/scoreboard.component.html +++ b/static/src/app/statistic/war-detail/scoreboard/scoreboard.component.html @@ -1,4 +1,4 @@ -
+
- Gesamt + Gesamt diff --git a/static/src/app/statistic/war-detail/scoreboard/scoreboard.component.ts b/static/src/app/statistic/war-detail/scoreboard/scoreboard.component.ts index 945fbbe..4d9b059 100644 --- a/static/src/app/statistic/war-detail/scoreboard/scoreboard.component.ts +++ b/static/src/app/statistic/war-detail/scoreboard/scoreboard.component.ts @@ -1,5 +1,4 @@ -import {Component, ElementRef, SimpleChanges, ViewChild} from "@angular/core"; -import {ActivatedRoute, Router} from "@angular/router"; +import {Component, ElementRef, EventEmitter, SimpleChanges, ViewChild} from "@angular/core"; import {War} from "../../../models/model-interfaces"; import {Fraction} from "../../../utils/fraction.enum"; @@ -7,13 +6,14 @@ import {Fraction} from "../../../utils/fraction.enum"; selector: 'scoreboard', templateUrl: './scoreboard.component.html', inputs: ['war', 'fractionFilterSelected'], + outputs: ['playerTabSwitch'], styleUrls: ['./scoreboard.component.css', '../../../style/list-entry.css', '../../../style/hide-scrollbar.css'] }) export class ScoreboardComponent { readonly fraction = Fraction; - @ViewChild('overview') private overviewContainer: ElementRef; + playerTabSwitch = new EventEmitter(); war: War; @@ -30,16 +30,14 @@ export class ScoreboardComponent { sortDescending: 'glyphicon glyphicon-triangle-bottom', }; - constructor(private route: ActivatedRoute, - private router: Router) { + constructor() { } ngOnInit() { } - selectPlayerDetail(playerName: string) { - this.router.navigate(['../../campaign-player/' + this.war.campaign + '/' + playerName], - {relativeTo: this.route}); + selectPlayerDetail(view: number, playerName: string) { + this.playerTabSwitch.emit({view: view, player: playerName}) } ngOnChanges(changes: SimpleChanges) { @@ -49,14 +47,6 @@ export class ScoreboardComponent { if (changes.fractionFilterSelected) { this.filterPlayersByFraction(this.fractionFilterSelected) } - this.scrollOverviewTop(); - } - - scrollOverviewTop() { - try { - this.overviewContainer.nativeElement.scrollTop = 0; - } catch (err) { - } } filterPlayersByFraction(fraction?: string) { diff --git a/static/src/app/statistic/war-detail/war-detail.component.css b/static/src/app/statistic/war-detail/war-detail.component.css index 11f1770..9f2dc98 100644 --- a/static/src/app/statistic/war-detail/war-detail.component.css +++ b/static/src/app/statistic/war-detail/war-detail.component.css @@ -36,6 +36,6 @@ color: #FFF !important; } -.nav-tabs > li.deactivated > a.nav-link{ - cursor: not-allowed!important; +.nav-tabs > li.deactivated > a.nav-link { + cursor: not-allowed !important; } diff --git a/static/src/app/statistic/war-detail/war-detail.component.html b/static/src/app/statistic/war-detail/war-detail.component.html index 44e04a0..ea77b1b 100644 --- a/static/src/app/statistic/war-detail/war-detail.component.html +++ b/static/src/app/statistic/war-detail/war-detail.component.html @@ -66,13 +66,20 @@ + [fractionFilterSelected]="fractionFilterSelected" + (playerTabSwitch)="switchToPlayerTab($event)"> + +
diff --git a/static/src/app/statistic/war-detail/war-detail.component.ts b/static/src/app/statistic/war-detail/war-detail.component.ts index 5560a9e..8f22cec 100644 --- a/static/src/app/statistic/war-detail/war-detail.component.ts +++ b/static/src/app/statistic/war-detail/war-detail.component.ts @@ -20,6 +20,10 @@ export class WarDetailComponent { logData; + singlePlayerView: number; + + playerDetailName: string; + tab: number; fractionStatsInitialized: boolean; @@ -45,7 +49,7 @@ export class WarDetailComponent { .subscribe(war => { this.war = war; - this.tab = 0; + this.switchTab(0); this.fractionStatsInitialized = false; this.fractionFilterSelected = undefined; @@ -62,6 +66,17 @@ export class WarDetailComponent { this.fractionStatsInitialized = true; }); } + window.scroll({left: 0, top: 0, behavior: 'smooth'}); + } + + /** + * called by EventEmitter, + * @param event with fields: 'view' (0 = war-detail, 1 = campaign-detail); 'player' = player name + */ + switchToPlayerTab(event) { + this.singlePlayerView = event.view; + this.playerDetailName = event.player; + this.switchTab(2); } filterPlayersByFraction(fraction?: string) { diff --git a/static/src/app/users/user-list/user-list.component.html b/static/src/app/users/user-list/user-list.component.html index 952dd50..0d664f9 100644 --- a/static/src/app/users/user-list/user-list.component.html +++ b/static/src/app/users/user-list/user-list.component.html @@ -31,7 +31,7 @@ [user]="user" (userDelete)="deleteUser(user)" (userSelected)="selectUser($event)" - (userAward)="awardUser($event, $event)" + (userAward)="awardUser($event)" [selected]="user._id == selectedUserId">
diff --git a/static/src/main.ts b/static/src/main.ts index 50ed715..57d0769 100644 --- a/static/src/main.ts +++ b/static/src/main.ts @@ -4,29 +4,6 @@ import {platformBrowserDynamic} from '@angular/platform-browser-dynamic'; import {AppModule} from './app/app.module'; import {environment} from './environments/environment'; - -import 'rxjs/add/observable/of'; -import 'rxjs/add/operator/retryWhen'; -import 'rxjs/add/observable/fromEvent'; -import 'rxjs/add/observable/from'; -import 'rxjs/add/observable/range'; -import 'rxjs/add/observable/timer'; -import 'rxjs/add/observable/merge'; -import 'rxjs/add/observable/interval'; - -import 'rxjs/add/operator/filter'; -import 'rxjs/add/operator/debounceTime'; -import 'rxjs/add/operator/distinctUntilChanged'; -import 'rxjs/add/operator/mergeMap'; -import 'rxjs/add/operator/switchMap'; -import 'rxjs/add/operator/do'; -import 'rxjs/add/operator/map'; -import 'rxjs/add/operator/retry'; -import 'rxjs/add/operator/bufferCount'; -import 'rxjs/add/operator/bufferTime'; -import 'rxjs/add/operator/take'; -import 'rxjs/add/operator/delay'; - if (environment.production) { enableProdMode(); } From a58840243184aa21df40780798580f2d465a6133 Mon Sep 17 00:00:00 2001 From: HardiReady Date: Mon, 13 Nov 2017 15:50:59 +0100 Subject: [PATCH 7/7] remove unused css --- static/src/styles.css | 8 -------- 1 file changed, 8 deletions(-) diff --git a/static/src/styles.css b/static/src/styles.css index 1eda07a..ab03687 100644 --- a/static/src/styles.css +++ b/static/src/styles.css @@ -47,11 +47,3 @@ form { #right { overflow: hidden; } - -#right-top { - overflow: hidden; -} - -#right-bottom { - overflow: hidden; -}