Skip to content

Commit

Permalink
beautiful charts
Browse files Browse the repository at this point in the history
  • Loading branch information
vinhill committed Jul 26, 2021
1 parent 5b5d403 commit 2e5e9ad
Show file tree
Hide file tree
Showing 12 changed files with 213 additions and 42 deletions.
4 changes: 2 additions & 2 deletions TTTStats/angular.json
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,8 @@
"budgets": [
{
"type": "initial",
"maximumWarning": "500kb",
"maximumError": "1mb"
"maximumWarning": "1mb",
"maximumError": "3mb"
},
{
"type": "anyComponentStyle",
Expand Down
4 changes: 3 additions & 1 deletion TTTStats/src/app/app.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { CardComponent } from './card/card.component';
import { OverviewComponent } from './overview/overview.component';
import { PlayerComponent } from './player/player.component';
import { RestttComponent } from './resttt/resttt.component';
import { DelayDirective } from './delay.directive';

import { ChartsModule } from 'ng2-charts';

Expand All @@ -16,7 +17,8 @@ import { ChartsModule } from 'ng2-charts';
CardComponent,
OverviewComponent,
PlayerComponent,
RestttComponent
RestttComponent,
DelayDirective
],
imports: [
BrowserModule,
Expand Down
6 changes: 6 additions & 0 deletions TTTStats/src/app/card/card.component.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
.card {
margin: 1em;
}
.masonry-item {
float: left;
}
11 changes: 8 additions & 3 deletions TTTStats/src/app/card/card.component.html
Original file line number Diff line number Diff line change
@@ -1,4 +1,9 @@
<div class="masonry-item col-sm-12 col-md-4">
<!-- Container for dynamic content from where the tag is used -->
<ng-content></ng-content>
<div class="masonry-item {{classes}}"><!--style="float:left"-->
<div class="card">
<h5 class="card-header">{{title}}</h5>
<div class="card-body">
<!-- Container for dynamic content from where the tag is used -->
<ng-content></ng-content>
</div>
</div>
</div>
29 changes: 26 additions & 3 deletions TTTStats/src/app/card/card.component.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,31 @@
import { Component } from '@angular/core';
import { Component, Input } from '@angular/core';

@Component({
selector: 'card',
templateUrl: './card.component.html',
styleUrls: ['./card.component.css', '../masonry.css']
styleUrls: ['./card.component.css']
})
export class CardComponent {}
export class CardComponent {
@Input() title!: string;

classes: string = "";

constructor() {
// Default value
this.size = "medium";
}

@Input() set size(size: string) {
if (size == "tiny") {
this.classes = "col-sm-6 col-md-5 col-lg-4 col-xl-3";
} else if (size == "small") {
this.classes = "col-sm-12 col-md-6 col-lg-4 col-xl-3";
} else if (size == "medium") {
this.classes = "col-sm-12 col-md-8 col-lg-6 col-xl-4";
} else if(size == "large") {
this.classes = "col-sm-12 col-md-12 col-lg-8 col-xl-6";
}else if (size == "xlarge") {
this.classes = "col-12";
}
}
}
60 changes: 60 additions & 0 deletions TTTStats/src/app/delay.directive.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
import { Directive, Input, OnInit, ElementRef } from '@angular/core';
import { RestttService } from './resttt.service';

@Directive({
selector: '[delay]'
})
export class DelayDirective implements OnInit {

constructor(private ref: ElementRef) {}

@Input() delay!: number;

ngOnInit() {
setTimeout(() => {
this.invert();
}, this.delay);
}

invert() {
if(this.ref.nativeElement.hidden) {
this.fadeIn();
}else {
this.fadeOut();
}
}

// https://stackoverflow.com/questions/6121203/how-to-do-fade-in-and-fade-out-with-javascript-and-css

fadeOut() {
let element = this.ref.nativeElement;
element.style.opacity = 1;

var op = 1; // initial opacity
var timer = setInterval(function () {
if (op <= 0.1){
clearInterval(timer);
element.hidden = true;
}
element.style.opacity = op;
element.style.filter = 'alpha(opacity=' + op * 100 + ")";
op -= op * 0.1;
}, 50);
}

fadeIn() {
let element = this.ref.nativeElement;
element.style.opacity = 0;
element.hidden = false;

var op = 0.05; // initial opacity
var timer = setInterval(function () {
if (op >= 1){
clearInterval(timer);
}
element.style.opacity = op;
element.style.filter = 'alpha(opacity=' + op * 100 + ")";
op += op * 0.1;
}, 30);
}
}
7 changes: 0 additions & 7 deletions TTTStats/src/app/masonry.css

This file was deleted.

28 changes: 11 additions & 17 deletions TTTStats/src/app/overview/overview.component.html
Original file line number Diff line number Diff line change
@@ -1,26 +1,20 @@
<div id="content-wrap" class="container">
<div class="d-flex justify-content-center">
<h1 class="display-3">TTT Overview</h1>
</div>
<div dataMasonry='{ "itemSelector": ".masonry-item" }'>
<!-- See https://www.npmjs.com/package/ng2-charts -->

<card>
<canvas baseChart
[data]="[[10,20,30], [30,20,10]]"
[labels]="['a', 'b', 'c']"
chartType="doughnut">
</canvas>
</card>

<card>
<resttt query="PlayerGameCount" display="text"></resttt>
<card title="Spiele">
<resttt query="PlayerGameCount" display="chart" label="player" data="rounds" type="bar" [legend]="false" [options]="{scales:{yAxes:[{ticks:{beginAtZero:true}}]}}"></resttt>
</card>
<card>
<resttt query="MapCount" display="table"></resttt>
<card title="Karten">
<resttt query="MapCount" display="chart" label="map" [datas]="['count']" type="doughnut"></resttt>
</card>
<card>
<resttt query="RoleCount" display="table"></resttt>
<card title="Rollen" size="large">
<resttt query="RoleCount" display="chart" label="role" data="count" type="pie"></resttt>
</card>
<card>
<resttt query="PlayerKillCount" display="table"></resttt>
<card title="Kills">
<resttt query="PlayerKillCount" display="table" [columns]="['player','kills','wrong','killsPerGame']"></resttt>
</card>

</div>
Expand Down
8 changes: 6 additions & 2 deletions TTTStats/src/app/player/player.component.html
Original file line number Diff line number Diff line change
@@ -1,8 +1,12 @@
<div id="content-wrap" class="container">
<h1>{{name}}</h1>
<div class="d-flex justify-content-center">
<h1 class="display-3">{{name}}</h1>
</div>
<div dataMasonry='{ "itemSelector": ".masonry-item" }'>

<card>Hello, World!</card>
<card title="Rollen">
<resttt query="PlayerRoles/{{name}}" display="chart" label="role" data="count" type="doughnut"></resttt>
</card>

</div>
</div>
9 changes: 9 additions & 0 deletions TTTStats/src/app/resttt/resttt.component.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
.btn-reload {
height: 3rem;
margin-top: 0.5rem;
margin-bottom: 0.5rem;
}
.spinner-border {
width: 5rem;
height: 5rem;
}
39 changes: 34 additions & 5 deletions TTTStats/src/app/resttt/resttt.component.html
Original file line number Diff line number Diff line change
@@ -1,29 +1,58 @@
<div *ngIf="loaded">

<!-- Text -->
<div *ngIf="display == 'text'">
{{stringify(result)}}
</div>

<!-- Table -->
<div *ngIf="display == 'table'">
<table class="table">
<thead>
<tr>
<th *ngFor="let key of keys(result[0])">{{key}}</th>
<th *ngFor="let key of columns">{{key}}</th>
</tr>
</thead>
<tbody>
<tr *ngFor="let row of result">
<td *ngFor="let key of keys(result[0])">{{row[key]}}</td>
<td *ngFor="let key of columns">{{row[key]}}</td>
</tr>
</tbody>
</table>
</div>

<!-- Chart -->
<div *ngIf="display == 'chart'">
To be implemented...
<canvas baseChart *ngIf="data != ''"
[data]="get_column(data)"
[labels]="get_column(label)"
[chartType]="type"
[legend]="legend"
[options]="options">
</canvas>
<canvas baseChart *ngIf="datas.length != 0"
[data]="get_columns(datas)"
[labels]="get_column(label)"
[chartType]="type"
[legend]="legend"
[options]="options">
</canvas>
</div>
</div>

<!-- Loading -->
<div *ngIf="!loaded">
<div class="spinner-border text-success" role="status">
<span class="sr-only">Loading...</span>
<div class="row">
<div class="col-4"></div>
<div class="col-4">
<div class="d-flex justify-content-center">
<div class="spinner-border text-secondary" role="status"></div>
</div>
</div>
<div class="col-4">
<div class="d-flex flex-row-reverse">
<button type="button" class="btn btn-secondary btn-reload" (click)="load()" [delay]="2500" hidden>Reload</button>
</div>
</div>
</div>
</div>
50 changes: 48 additions & 2 deletions TTTStats/src/app/resttt/resttt.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,41 @@ export class RestttComponent implements OnInit {
loaded: boolean = false;
result: any = "";

// REST Query
@Input() query!: string;
// Display mode
@Input() display!: string;

constructor(public resttt: RestttService) { }
// table column keys
@Input() columns: string[] = [];

async ngOnInit() {
// chart data keys
@Input() data: string = "";
@Input() datas: string[] = [];
// chart label key
@Input() label: string = "";
// chart type, see https://www.npmjs.com/package/ng2-charts
@Input() type: any = "";
// chart legend toggle
@Input() legend: boolean = true;
// chart options
@Input() options: any = "";

constructor(private resttt: RestttService) { }

ngOnInit() {
this.load();
}

async load() {
this.loaded = false;
this.result = await this.resttt.get(this.query);
console.log(this.result);
this.loaded = true;
// If no columns where provided, show all
if (this.columns.length == 0 && this.result.length != 0) {
this.columns = this.keys(this.result[0]);
}
}

stringify(obj: any): string {
Expand All @@ -28,4 +55,23 @@ export class RestttComponent implements OnInit {
return Object.keys(obj);
}

get_columns(keys: string[]): any {
/*
[{c1: 0, c2: 1}, {c1: 3, c2: 2}]
to
{c1: [0, 3], c2: [1,2]}
*/
let res: any = [];
for (let key of keys) {
res.push(this.result.map(function(row: any) {
return row[key]
}));
}
return res;
}

get_column(key: string): any {
return this.get_columns([key])[0];
}

}

0 comments on commit 2e5e9ad

Please sign in to comment.