Compare commits
	
		
			3 Commits 
		
	
	
		
			42cfadb9e9
			...
			99304649ea
		
	
	| Author | SHA1 | Date | 
|---|---|---|
|  | 99304649ea | |
|  | 8cabea74fd | |
|  | dfaddfa992 | 
|  | @ -644,11 +644,6 @@ | |||
|         } | ||||
|       } | ||||
|     }, | ||||
|     "@swimlane/ngx-datatable": { | ||||
|       "version": "13.0.1", | ||||
|       "resolved": "https://registry.npmjs.org/@swimlane/ngx-datatable/-/ngx-datatable-13.0.1.tgz", | ||||
|       "integrity": "sha512-jjMEzQhXcdD+jfKNp+7U61lWx9ZzSGDn9QbpY6pJOJwz+E2CKeek6OouT5Qcc4MY4oFL9g/SZoPjLf90cbNIRw==" | ||||
|     }, | ||||
|     "@types/jasmine": { | ||||
|       "version": "2.5.38", | ||||
|       "resolved": "https://registry.npmjs.org/@types/jasmine/-/jasmine-2.5.38.tgz", | ||||
|  |  | |||
|  | @ -29,7 +29,6 @@ | |||
|     "@angular/platform-browser-dynamic": "^6.0.7", | ||||
|     "@angular/router": "^6.0.7", | ||||
|     "@swimlane/ngx-charts": "^8.1.0", | ||||
|     "@swimlane/ngx-datatable": "^13.0.1", | ||||
|     "bootstrap": "^3.3.7", | ||||
|     "d3": "^4.11.0", | ||||
|     "file-saver": "^1.3.8", | ||||
|  |  | |||
|  | @ -11,71 +11,53 @@ h2 { | |||
|   margin: 20px 0 0 10%; | ||||
| } | ||||
| 
 | ||||
| ngx-datatable { | ||||
|   width: 345px; | ||||
|   margin: 3% 5% 0 5%; | ||||
|   height: 310px; | ||||
| .highscore-table-container { | ||||
|   width: 320px; | ||||
|   max-height: 394px; | ||||
|   margin: 100px 0 0 8%; | ||||
|   float: left; | ||||
|   border: solid #dfdfdf 1px; | ||||
|   border-radius: 10px 10px 2px 2px; | ||||
| } | ||||
| 
 | ||||
| :host /deep/ .datatable-header { | ||||
|   width: 350px !important; | ||||
|   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 { | ||||
|   overflow-x: hidden; | ||||
|   overflow-y: auto; | ||||
|   border: solid #dfdfdf 1px; | ||||
|   box-shadow: 3px 3px 1px -2px rgba(0,0,0,.2), 0 2px 2px 0 rgba(0,0,0,.14), 0 1px 5px 0 rgba(0,0,0,.12); | ||||
| } | ||||
| 
 | ||||
| :host /deep/ .datatable-body-row { | ||||
|   color: #222222; | ||||
|   border-bottom: 1px solid grey; | ||||
| .highscore-table { | ||||
|   width: 100%; | ||||
| } | ||||
| 
 | ||||
| :host /deep/ .datatable-body-row:hover { | ||||
|   background-color: #f7f7f7; | ||||
| table.mat-table img { | ||||
|   filter: invert(60%); | ||||
|   margin-left: -15px; | ||||
| } | ||||
| 
 | ||||
| :host /deep/ .ngx-datatable.fixed-header .datatable-header .datatable-header-inner .datatable-header-cell { | ||||
|   margin: auto; | ||||
| :host /deep/ table.mat-table > thead { | ||||
|   position: absolute; | ||||
|   width: 320px; | ||||
|   display: inherit; | ||||
|   margin-left: -1px; | ||||
|   margin-top: -57px; | ||||
|   border: 1px solid #dadada; | ||||
| } | ||||
| 
 | ||||
| .mat-column-kill, .mat-column-friendlyFire, .mat-column-revive, .mat-column-flagTouch, | ||||
| .mat-column-vehicleLight, .mat-column-vehicleHeavy, .mat-column-vehicleAir, .mat-column-death, .mat-column-respawn { | ||||
|   width: 67px; | ||||
|   text-indent: 14px; | ||||
| } | ||||
| 
 | ||||
| /* Table Scrollbar BEGIN */ | ||||
| 
 | ||||
| :host /deep/ .ngx-datatable.scroll-vertical .datatable-body::-webkit-scrollbar { | ||||
| .highscore-table-container::-webkit-scrollbar { | ||||
|   width: 12px; | ||||
| } | ||||
| 
 | ||||
| :host /deep/ .ngx-datatable.scroll-vertical .datatable-body::-webkit-scrollbar-track { | ||||
|   -webkit-box-shadow: inset 0 0 6px rgba(0, 0, 0, 0.3); | ||||
|   border-radius: 10px; | ||||
| .highscore-table-container::-webkit-scrollbar-track { | ||||
|   border-left: 1px solid #f1f1f1; | ||||
| } | ||||
| 
 | ||||
| :host /deep/ .ngx-datatable.scroll-vertical .datatable-body::-webkit-scrollbar-thumb { | ||||
|   border-radius: 10px; | ||||
|   background: #4b4b4b; | ||||
|   -webkit-box-shadow: inset 0 0 6px rgba(255, 255, 255, 0.5); | ||||
| .highscore-table-container::-webkit-scrollbar-thumb { | ||||
|   background: rgb(234, 234, 234); | ||||
| } | ||||
| 
 | ||||
| /* Table Scrollbar END */ | ||||
|  |  | |||
|  | @ -3,6 +3,7 @@ | |||
| 
 | ||||
|   <div class="input-group search-field"> | ||||
|     <input id="search-tasks" | ||||
|            markForCheck | ||||
|            placeholder="Spielername (mehrere mit '&' trennen)" | ||||
|            type="text" #query class="form-control" | ||||
|            (keyup.enter)="filterPlayers()" | ||||
|  | @ -16,41 +17,37 @@ | |||
|   </div> | ||||
| 
 | ||||
|   <div *ngFor="let attributeMap of playerAttributeDisplayNames"> | ||||
|     <ngx-datatable | ||||
|       [rows]="players[attributeMap.prop]" | ||||
|       [messages]="emptyMessage" | ||||
|       [headerHeight]="cellHeight" | ||||
|       [rowHeight]="cellHeight" | ||||
|       [cssClasses]='customClasses' | ||||
|       [columnMode]="'force'" | ||||
|       [scrollbarV]="true" | ||||
|       [selectionType]="'single'"> | ||||
|       <ngx-datatable-column [width]="numberColWidth" name="#" prop="num"></ngx-datatable-column> | ||||
|       <ngx-datatable-column name="Spieler" prop="name" [width]="nameColWidth" style="padding-left:10px"> | ||||
|         <ng-template ngx-datatable-cell-template let-row="row" let-value="value"> | ||||
|         <span class="player-name" | ||||
|               [style.color]="row['fraction'] === 'BLUFOR' ? fraction.COLOR_BLUFOR : fraction.COLOR_OPFOR"> | ||||
|           {{value}} | ||||
|         </span> | ||||
|         </ng-template> | ||||
|       </ngx-datatable-column> | ||||
|     <div class="highscore-table-container"> | ||||
|       <table mat-table matSort | ||||
|              [dataSource]="players[attributeMap.prop]" | ||||
|              class="mat-elevation-z8 highscore-table"> | ||||
| 
 | ||||
|       <ngx-datatable-column [width]="valueColWidth" prop="{{attributeMap.prop}}"> | ||||
|         <ng-template ngx-datatable-header-template let-sort="sortFn"> | ||||
|         <span class="datatable-header-cell-wrapper"> | ||||
|           <span class="datatable-header-cell-label text-truncate" matTooltip="{{attributeMap.head}}" (click)="sort()"> | ||||
|             <img src="../../../../assets/scoreboard/{{attributeMap.prop}}.png" alt="{{attributeMap.head}}"> | ||||
|           </span> | ||||
|         </span> | ||||
|         </ng-template> | ||||
|         <ng-template ngx-datatable-cell-template let-row="row" let-value="value"> | ||||
|         <span style="padding-left: 7px;"> | ||||
|           {{value}} | ||||
|         </span> | ||||
|         </ng-template> | ||||
|       </ngx-datatable-column> | ||||
|     </ngx-datatable> | ||||
|         <ng-container matColumnDef="num"> | ||||
|           <th mat-header-cell *matHeaderCellDef>#</th> | ||||
|           <td mat-cell *matCellDef="let element">{{element.num}}</td> | ||||
|         </ng-container> | ||||
| 
 | ||||
|         <ng-container matColumnDef="name"> | ||||
|           <th mat-header-cell *matHeaderCellDef>Name</th> | ||||
|           <td mat-cell *matCellDef="let element" | ||||
|               [style.color]="element['fraction'] === 'BLUFOR' ? fraction.COLOR_BLUFOR : fraction.COLOR_OPFOR"> | ||||
|             {{element.name}} | ||||
|           </td> | ||||
|         </ng-container> | ||||
| 
 | ||||
|         <ng-container matColumnDef="{{attributeMap.prop}}"> | ||||
|           <th mat-header-cell *matHeaderCellDef> | ||||
|             <img src="../../../../assets/scoreboard/{{attributeMap.prop}}.png" | ||||
|                  matTooltip="{{attributeMap.head}}" | ||||
|                  alt="{{attributeMap.head}}"> | ||||
|           </th> | ||||
|           <td mat-cell *matCellDef="let element"> {{element[attributeMap.prop]}}</td> | ||||
|         </ng-container> | ||||
| 
 | ||||
|         <tr mat-header-row *matHeaderRowDef="['num', 'name', attributeMap.prop];"></tr> | ||||
|         <tr mat-row *matRowDef="let row; columns: ['num', 'name', attributeMap.prop];"></tr> | ||||
|       </table> | ||||
|     </div> | ||||
|   </div> | ||||
| 
 | ||||
| </div> | ||||
| 
 | ||||
|  |  | |||
|  | @ -30,21 +30,6 @@ export class StatisticHighScoreComponent implements OnInit { | |||
| 
 | ||||
|   playerAttributeDisplayNames = PlayerUtils.attributeDisplayNames.slice(2, PlayerUtils.attributeDisplayNames.length); | ||||
| 
 | ||||
|   cellHeight = 40; | ||||
| 
 | ||||
|   numberColWidth = 60; | ||||
| 
 | ||||
|   nameColWidth = 210; | ||||
| 
 | ||||
|   valueColWidth = 55; | ||||
| 
 | ||||
|   emptyMessage = {emptyMessage: 'Keine Einträge'}; | ||||
| 
 | ||||
|   customClasses = { | ||||
|     sortAscending: 'glyphicon glyphicon-triangle-top', | ||||
|     sortDescending: 'glyphicon glyphicon-triangle-bottom', | ||||
|   }; | ||||
| 
 | ||||
|   readonly fraction = Fraction; | ||||
| 
 | ||||
|   constructor(private route: ActivatedRoute, | ||||
|  | @ -97,7 +82,6 @@ export class StatisticHighScoreComponent implements OnInit { | |||
| 
 | ||||
|   private filterPlayerAttribute(attribute) { | ||||
|     const query = this.searchTerm.value.toLowerCase().split('&'); | ||||
| 
 | ||||
|     return this.playersStored[attribute].filter(player => { | ||||
|       for (let i = 0; i < query.length; i++) { | ||||
|         if (query[i].trim() !== '' && player.name.toLowerCase().includes(query[i].trim())) { | ||||
|  | @ -107,5 +91,4 @@ export class StatisticHighScoreComponent implements OnInit { | |||
|       return false; | ||||
|     }); | ||||
|   } | ||||
| 
 | ||||
| } | ||||
|  |  | |||
|  | @ -5,7 +5,6 @@ import {statsRouterModule, statsRoutingComponents} from './stats.routing'; | |||
| import {WarService} from '../services/logs/war.service'; | ||||
| import {NgxChartsModule} from '@swimlane/ngx-charts'; | ||||
| import {CampaignService} from '../services/logs/campaign.service'; | ||||
| import {NgxDatatableModule} from '@swimlane/ngx-datatable'; | ||||
| import {PlayerService} from '../services/logs/player.service'; | ||||
| import {LogsService} from '../services/logs/logs.service'; | ||||
| import {MatButtonModule, MatButtonToggleModule, MatExpansionModule, MatTableModule, MatSortModule} from '@angular/material'; | ||||
|  | @ -13,8 +12,8 @@ import {MatButtonModule, MatButtonToggleModule, MatExpansionModule, MatTableModu | |||
| 
 | ||||
| @NgModule({ | ||||
|   declarations: statsRoutingComponents, | ||||
|   imports: [CommonModule, SharedModule, statsRouterModule, NgxChartsModule, NgxDatatableModule, | ||||
|     MatButtonModule, MatExpansionModule, MatButtonToggleModule, MatTableModule, MatSortModule], | ||||
|   imports: [CommonModule, SharedModule, statsRouterModule, NgxChartsModule, MatButtonModule, MatExpansionModule, | ||||
|     MatButtonToggleModule, MatTableModule, MatSortModule], | ||||
|   providers: [WarService, CampaignService, PlayerService, LogsService] | ||||
| }) | ||||
| export class StatsModule { | ||||
|  |  | |||
|  | @ -1,3 +1,11 @@ | |||
| .scoreboard-table { | ||||
|   height: 68vh; | ||||
|   width:fit-content; | ||||
|   border: 1px solid #dadada; | ||||
|   overflow-x: auto; | ||||
|   margin:auto; | ||||
| } | ||||
| 
 | ||||
| .in-table-btn { | ||||
|   position: absolute; | ||||
|   margin-top: -5px; | ||||
|  | @ -12,6 +20,16 @@ table.mat-table img { | |||
|   filter: invert(60%); | ||||
| } | ||||
| 
 | ||||
| :host /deep/ table.mat-table > thead { | ||||
|   position: absolute; | ||||
|   display: inherit; | ||||
| } | ||||
| 
 | ||||
| :host /deep/ table.mat-table > tbody { | ||||
|   margin-top: 60px; | ||||
|   display: block; | ||||
| } | ||||
| 
 | ||||
| .mat-column-name { | ||||
|   width: 200px; | ||||
| } | ||||
|  | @ -25,6 +43,18 @@ table.mat-table img { | |||
|   text-indent: 9px; | ||||
| } | ||||
| 
 | ||||
| th.mat-column-interact { | ||||
|   padding-left: 36px; | ||||
|   background: white; | ||||
|   position: relative; | ||||
|   z-index: 100; | ||||
| } | ||||
| 
 | ||||
| /* TABLE SCROLLBAR */ | ||||
| div::-webkit-scrollbar-thumb { | ||||
|   border-top: solid white 56px; | ||||
| } | ||||
| 
 | ||||
| /* MAT ICON BUTTON */ | ||||
| 
 | ||||
| :host/deep/.mat-table .mat-icon { | ||||
|  |  | |||
|  | @ -1,9 +1,9 @@ | |||
| <div class="fade-in" style="border-top: 1px solid #dadada; overflow-x: auto"> | ||||
| <div class="fade-in scoreboard-table"> | ||||
| 
 | ||||
|   <table mat-table matSort | ||||
|          [dataSource]="sortedRows" | ||||
|          matSortActive="{{tableHead[2].prop}}" matSortDirection="asc" matSortDisableClear | ||||
|          (matSortChange)="sortData($event)" | ||||
|          (matSortChange)="sortScoreboardData($event)" | ||||
|          class="mat-elevation-z8"> | ||||
| 
 | ||||
|     <ng-container matColumnDef="{{tableHead[0].prop}}"> | ||||
|  | @ -29,7 +29,7 @@ | |||
|     </ng-container> | ||||
| 
 | ||||
|     <ng-container matColumnDef="interact"> | ||||
|       <th mat-header-cell *matHeaderCellDef></th> | ||||
|       <th mat-header-cell *matHeaderCellDef> </th> | ||||
|       <td mat-cell *matCellDef="let element"> | ||||
|         <button mat-icon-button | ||||
|                 matTooltip="Kampagnenstatistik für {{element.name}}" | ||||
|  |  | |||
|  | @ -4,6 +4,7 @@ import {Fraction} from '../../../utils/fraction.enum'; | |||
| import {PlayerUtils} from '../../../utils/player-utils'; | ||||
| import {saveAs} from 'file-saver/FileSaver'; | ||||
| import {MatSort, Sort} from '@angular/material'; | ||||
| import {SortUtils} from '../../../utils/sort-utils'; | ||||
| 
 | ||||
| @Component({ | ||||
|   selector: 'cc-scoreboard', | ||||
|  | @ -32,6 +33,8 @@ export class ScoreboardComponent implements OnChanges { | |||
| 
 | ||||
|   sortedRows = []; | ||||
| 
 | ||||
|   currentSort = new MatSort(); | ||||
| 
 | ||||
|   displayedColumns = this.tableHead.map(head => head.prop); | ||||
| 
 | ||||
|   reorderable = false; | ||||
|  | @ -55,10 +58,8 @@ export class ScoreboardComponent implements OnChanges { | |||
|   ngOnChanges(changes: SimpleChanges) { | ||||
|     if (changes.war) { | ||||
|       this.rows = changes.war.currentValue.players; | ||||
| 
 | ||||
|       const sort = new MatSort(); | ||||
|       sort.active = 'kill'; | ||||
|       this.sortData(sort); | ||||
|       this.currentSort.active = 'kill'; | ||||
|       this.sortScoreboardData(this.currentSort); | ||||
| //      this.elRef.nativeElement
 | ||||
| //          .querySelector('.datatable-body')
 | ||||
| //          .scrollTo(0, 0);
 | ||||
|  | @ -76,9 +77,13 @@ export class ScoreboardComponent implements OnChanges { | |||
|     } else { | ||||
|       this.rows = this.war.players; | ||||
|     } | ||||
|     this.sortScoreboardData(this.currentSort); | ||||
|   } | ||||
| 
 | ||||
|   sortData(sort: Sort) { | ||||
|   sortScoreboardData(sort: MatSort) { | ||||
|     if (sort) { | ||||
|       this.currentSort = sort; | ||||
|     } | ||||
|     const data = this.rows.slice(); | ||||
|     if (!sort.active || sort.direction === '') { | ||||
|       this.sortedRows = data; | ||||
|  | @ -88,14 +93,10 @@ export class ScoreboardComponent implements OnChanges { | |||
|     this.sortedRows = data.sort((a, b) => { | ||||
|       const isAsc = sort.direction === 'desc'; | ||||
|       const sortProperty = sort.active; | ||||
|       return this.compare(a[sortProperty], b[sortProperty], isAsc); | ||||
|       return SortUtils.compare(a[sortProperty], b[sortProperty], isAsc); | ||||
|     }); | ||||
|   } | ||||
| 
 | ||||
|   compare(a, b, isAsc) { | ||||
|     return (a < b ? -1 : 1) * (isAsc ? 1 : -1); | ||||
|   } | ||||
| 
 | ||||
|   exportCSV() { | ||||
|     let csvOut = ''; | ||||
|     for (let i = 0; i < this.tableHead.length; i++) { | ||||
|  |  | |||
|  | @ -0,0 +1,6 @@ | |||
| export class SortUtils { | ||||
| 
 | ||||
|   public static compare(a, b, isAsc) { | ||||
|     return (a < b ? -1 : 1) * (isAsc ? 1 : -1); | ||||
|   } | ||||
| } | ||||
		Loading…
	
		Reference in New Issue