Updated Hero Points Page with latest work
This commit is contained in:
parent
e1bf569f37
commit
ab0ba52b6f
12 changed files with 404 additions and 231 deletions
|
@ -26,8 +26,8 @@ import { OrgSnippetsService } from './providers/org-snippets.service';
|
|||
import { CustSnippetsService } from './providers/cust-snippets.service';
|
||||
import { CustPiesService } from './providers/cust-pies.service';
|
||||
import { MedalsService } from './providers/medals.service';
|
||||
//import { HeroPointsSnippetsService } from './providers/hero-points-snippets.service';
|
||||
//import { HeroPointsStatsService } from './providers/hero-points-stats.service';
|
||||
import { HeroPointsSnippetsService } from './providers/hero-points-snippets.service';
|
||||
import { HeroPointsGraphService } from './providers/hero-points-graph.service';
|
||||
|
||||
// Layouts
|
||||
import { FullLayoutComponent } from './layouts/full-layout.component';
|
||||
|
@ -77,10 +77,10 @@ import { NgPipesModule } from 'ngx-pipes';
|
|||
OrgSnippetsService,
|
||||
CustGraphsService,
|
||||
CustSnippetsService,
|
||||
//HeroPointsSnippetsService,
|
||||
//HeroPointsStatsService,
|
||||
HeroPointsSnippetsService,
|
||||
MedalsService,
|
||||
CustPiesService,
|
||||
HeroPointsGraphService,
|
||||
{
|
||||
provide: LocationStrategy,
|
||||
useClass: HashLocationStrategy
|
||||
|
|
|
@ -26,7 +26,8 @@ import { HeroPointsComponent } from './hero-points.component';
|
|||
import { GraphWidget } from '../widgets/graph-widget.component';
|
||||
import { OrgBarSnippetComponent } from '../snippets/org-snippet-bar.component';
|
||||
import { CustBarSnippetComponent } from '../snippets/cust-snippet-bar.component';
|
||||
//import { HeroPointsSnippetBarComponent } from '../snippets/hero-points-snippet-bar.component';
|
||||
import { HeroPointsSnippetBarComponent } from '../snippets/hero-points-snippet-bar.component';
|
||||
import { HeroPointsGraphWidget } from '../widgets/hero-points-graph-widget.component';
|
||||
import { GraphPanel } from '../panels/graph-panel.component';
|
||||
import { PiePanel } from '../panels/pie-panel.component';
|
||||
|
||||
|
@ -80,7 +81,8 @@ import { NgPipesModule } from 'ngx-pipes';
|
|||
GraphWidget,
|
||||
OrgBarSnippetComponent,
|
||||
CustBarSnippetComponent,
|
||||
//HeroPointsSnippetBarComponent,
|
||||
HeroPointsSnippetBarComponent,
|
||||
HeroPointsGraphWidget,
|
||||
GraphPanel,
|
||||
PiePanel,
|
||||
HeroPointsComponent,
|
||||
|
|
|
@ -1,14 +1,14 @@
|
|||
<div class="animated fadeIn">
|
||||
<!--<snippet-bar-hero-points></snippet-bar-hero-points>--><!-- Snippet for hero points (four circles) -->
|
||||
<snippet-bar-hero-points></snippet-bar-hero-points><!-- Snippet for hero points (four circles) -->
|
||||
<div class="row"> <!-- second row -->
|
||||
<div class="col-md-6 col-xl-3"> <!-- Hero points gain charts -->
|
||||
<div *ngFor="let widget of widgetList"> <!-- Points gain line graph -->
|
||||
<!--<widget-graph *ngIf="widget.type == 'graph'"
|
||||
<hero-points-widget-graph *ngIf="widget.type == 'graph'"
|
||||
[graphName]="widget.name"
|
||||
[graphTitle]="widget.title"
|
||||
[graphIcon]="widget.icon"
|
||||
[dataType]="widget.dataType">
|
||||
</widget-graph>-->
|
||||
</hero-points-widget-graph>
|
||||
</div> <!-- let widget of widgetList -->
|
||||
<div class="card"> <!-- Points gain by week charts -->
|
||||
<div class="card-block">
|
||||
|
@ -21,41 +21,41 @@
|
|||
<ul class="horizontal-bars type-2">
|
||||
<li> <!-- This Week -->
|
||||
<span class="title">This Week</span>
|
||||
<span class="value">{{ transactionListWeek | filterBy: ['weekId']: (transactionListWeek | pluck: 'weekId' | max) | pluck: 'pointsEarned' }}<span class="text-muted small"> ({{( transactionListWeek | filterBy: ['weekId']: (transactionListWeek | pluck: 'weekId' | max) | pluck: 'pointsEarned' ) / ( transactionListWeek | pluck: 'pointsEarned' | max ) | percent:'1.0-0' }})</span></span>
|
||||
<span class="value">{{ heroPointsStats.this_week }}<span class="text-muted small"> ({{ heroPointsStats.this_week / heroPointsStats.max | percent:'1.0-0' }})</span></span>
|
||||
<div class="bars">
|
||||
<div class="progress" style="height: 6px;">
|
||||
<div class="progress-bar bg-success" role="progressbar"
|
||||
style="width: 39%" aria-valuemin="0" aria-valuemax="100"></div>
|
||||
[style.width]="heroPointsStats.this_week / heroPointsStats.max | percent:'1.0-0'" aria-valuemin="0" aria-valuemax="100"></div>
|
||||
</div> <!-- progress -->
|
||||
</div> <!-- bars -->
|
||||
</li>
|
||||
<li> <!-- Last Week -->
|
||||
<span class="title">Last Week</span>
|
||||
<span class="value">{{ transactionListWeek | filterBy: ['weekId']: (transactionListWeek | pluck: 'weekId' | max) - 1 | pluck: 'pointsEarned' }}<span class="text-muted small"> ({{( transactionListWeek | filterBy: ['weekId']: (transactionListWeek | pluck: 'weekId' | max) - 1 | pluck: 'pointsEarned' ) / ( transactionListWeek | pluck: 'pointsEarned' | max ) | percent:'1.0-0' }})</span></span>
|
||||
<span class="value">{{ heroPointsStats.last_week }}<span class="text-muted small"> ({{ heroPointsStats.last_week / heroPointsStats.max | percent:'1.0-0' }})</span></span>
|
||||
<div class="bars">
|
||||
<div class="progress" style="height: 6px;">
|
||||
<div class="progress-bar bg-success" role="progressbar"
|
||||
style="width: 100%" aria-valuemin="0" aria-valuemax="100"></div>
|
||||
[style.width]="heroPointsStats.last_week / heroPointsStats.max | percent:'1.0-0'" aria-valuemin="0" aria-valuemax="100"></div>
|
||||
</div> <!-- progress -->
|
||||
</div> <!-- bars -->
|
||||
</li>
|
||||
<li> <!-- Week Maximum -->
|
||||
<span class="title">Week Maximum</span>
|
||||
<span class="value">{{ transactionListWeek | pluck: 'pointsEarned' | max }}<span class="text-muted small"> (100%)</span></span>
|
||||
<span class="value">{{ heroPointsStats.max }}<span class="text-muted small"> ({{ heroPointsStats.max / heroPointsStats.max | percent:'1.0-0' }})</span></span>
|
||||
<div class="bars">
|
||||
<div class="progress" style="height: 6px;">
|
||||
<div class="progress-bar bg-success" role="progressbar"
|
||||
style="width: 100%" aria-valuemin="0" aria-valuemax="100"></div>
|
||||
[style.width]="heroPointsStats.max / heroPointsStats.max | percent:'1.0-0'" aria-valuemin="0" aria-valuemax="100"></div>
|
||||
</div> <!-- progress -->
|
||||
</div> <!-- bars -->
|
||||
</li>
|
||||
<li> <!-- Weekly Average -->
|
||||
<span class="title">Weekly Average</span>
|
||||
<span class="value">{{ ((transactionListWeek | pluck: 'pointsEarned' | sum) / (transactionListWeek.length)) | round }}<span class="text-muted small"> ({{ (((transactionListWeek | pluck: 'pointsEarned' | sum) / (transactionListWeek.length)) | round ) / ( transactionListWeek | pluck: 'pointsEarned' | max ) | percent:'1.0-0' }})</span></span>
|
||||
<span class="value">{{ heroPointsStats.avg }}<span class="text-muted small"> ({{ heroPointsStats.avg / heroPointsStats.max | percent:'1.0-0' }})</span></span>
|
||||
<div class="bars">
|
||||
<div class="progress" style="height: 6px;">
|
||||
<div class="progress-bar bg-success" role="progressbar"
|
||||
style="width: 51%" aria-valuemin="0" aria-valuemax="100"></div>
|
||||
[style.width]="heroPointsStats.avg / heroPointsStats.max | percent:'1.0-0'" aria-valuemin="0" aria-valuemax="100"></div>
|
||||
</div> <!-- progess -->
|
||||
</div> <!-- bars -->
|
||||
</li>
|
||||
|
@ -106,7 +106,7 @@
|
|||
</div> <!-- if noUserList -->
|
||||
</div>
|
||||
<div class="col-md-6 col-xl-6"> <!-- Medal Table -->
|
||||
<div *ngIf="!noMedalList">
|
||||
<div *ngIf="!noGlobalMedalList && !noOrganisationMedalList">
|
||||
<table class="table header-fixed">
|
||||
<thead>
|
||||
<tr>
|
||||
|
@ -115,110 +115,140 @@
|
|||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<ng-container *ngFor="let groupNo of medalList | unique: 'medalGroupId'; let i = index"> <!-- ngFor each group of medals (global) -->
|
||||
<ng-container *ngIf="(medalList | filterBy: ['title']: groupNo.title: search: true).length > 1"> <!-- if the group is longer than 1 -->
|
||||
<ng-container *ngFor="let medals of globalMedalList"> <!-- ngFor each group of medals (global) -->
|
||||
<ng-container *ngFor="let group of medals | values; let groupIndex = index">
|
||||
<ng-container *ngIf="(group[0] | values).length - 1 > 1"> <!-- if the group is longer than 1 -->
|
||||
<!-- *ngIf 'global' medal and is/isn't expanded (headers)-->
|
||||
<tr *ngIf="groupNo.expanded && groupNo.medalType == 'global'" (click)="groupNo.expanded = false" [ngStyle]="{'background-color': '#20A8D8', 'color': '#ffffff' }">
|
||||
<td class="col-3">{{groupNo.title}}</td>
|
||||
<tr *ngIf="group.expanded" (click)="group.expanded = false" [ngStyle]="{'background-color':(group[0] | values | filterBy: ['awarded']: 'true' | pluck: 'awarded').length === (group[0] | values | filterBy: ['awarded']).length ? '#5FBC47' : '#20A8D8', 'color': '#ffffff' }">
|
||||
<td class="col-3">{{(medals | keys)[groupIndex]}}</td>
|
||||
<td class="col-6">Click to collapse</td>
|
||||
<td class="col-1">-</td>
|
||||
<td class="col-2" [ngStyle]="{'text-align': 'right'}">{{ ((medalList | filterBy: ['medalType']: 'global' | filterBy: ['title']: groupNo.title: search: true) | filterBy: ['unlocked']: true).length }}/{{ (medalList | filterBy: ['medalType']: 'global'| filterBy: ['title']: groupNo.title: search: true).length }}</td>
|
||||
<td class="col-2" [ngStyle]="{'text-align': 'right'}">{{(group[0] | values | filterBy: ['awarded']: 'true' | pluck: 'awarded').length}}/{{(group[0] | values | filterBy: ['awarded']).length}}</td>
|
||||
</tr>
|
||||
<tr *ngIf="!groupNo.expanded && groupNo.medalType == 'global'" (click)="groupNo.expanded = true" [ngStyle]="{'background-color': '#20A8D8', 'color': '#ffffff' }">
|
||||
<td class="col-3">{{groupNo.title}}</td>
|
||||
<tr *ngIf="!group.expanded" (click)="group.expanded = true" [ngStyle]="{'background-color':(group[0] | values | filterBy: ['awarded']: 'true' | pluck: 'awarded').length === (group[0] | values | filterBy: ['awarded']).length ? '#5FBC47' : '#20A8D8', 'color': '#ffffff' }">
|
||||
<td class="col-3">{{(medals | keys)[groupIndex]}}</td>
|
||||
<td class="col-6">Click to expand</td>
|
||||
<td class="col-1">+</td>
|
||||
<td class="col-2" [ngStyle]="{'text-align': 'right'}"> {{ ((medalList | filterBy: ['medalType']: 'global' | filterBy: ['title']: groupNo.title: search: true) | filterBy: ['unlocked']: true).length }}/{{ (medalList | filterBy: ['medalType']: 'global'| filterBy: ['title']: groupNo.title: search: true).length }}</td>
|
||||
<td class="col-2" [ngStyle]="{'text-align': 'right'}">{{(group[0] | values | filterBy: ['awarded']: 'true' | pluck: 'awarded').length}}/{{(group[0] | values | filterBy: ['awarded']).length}}</td>
|
||||
</tr>
|
||||
<!-- display actual medals -->
|
||||
<ng-container *ngFor="let medal of medalList | orderBy: ['+medalGroupId', '+reward']"> <!-- list each medal in each group, ordered by rewards, ascending order -->
|
||||
<tr *ngIf="groupNo.expanded && medal.medalGroupId == i && groupNo.medalType == 'global'" [ngStyle]="{'background-color':medal.unlocked === true ? '#89DD73' : '#F25F5F', 'color': '#ffffff' }">
|
||||
<td class="col-3">{{ medal.title }}</td>
|
||||
<td class="col-7">{{ medal.description }}</td>
|
||||
<td class="col-2" [ngStyle]="{'text-align': 'right'}">0/{{ medal.valueRequired }}</td> <!-- progress -->
|
||||
<ng-container *ngFor="let threshold of group[0] | values | orderBy: '+threshold'; let thresholdIndex = index"> <!-- list each medal in each group, ordered by threshold, ascending order -->
|
||||
<ng-container *ngIf="threshold | isObject">
|
||||
<ng-container *ngIf="threshold.awarded">
|
||||
<tr *ngIf="group.expanded" [ngStyle]="{'background-color': '#5FBC47', 'color': '#ffffff' }">
|
||||
<ng-container *ngIf="">
|
||||
</ng-container>
|
||||
<td class="col-3">{{(medals | keys)[groupIndex]}} {{thresholdIndex + 1}}</td>
|
||||
<td class="col-7">DESCRIPTION</td>
|
||||
<ng-container *ngIf="thresholdIndex + 1 != (group[0] | values | orderBy: '+threshold').length - 1">
|
||||
<td class="col-2" [ngStyle]="{'text-align': 'right'}">{{threshold.threshold}}/{{threshold.threshold}}</td> <!-- progress -->
|
||||
</ng-container>
|
||||
<ng-container *ngIf="thresholdIndex + 1 == (group[0] | values | orderBy: '+threshold').length - 1">
|
||||
<td class="col-2" [ngStyle]="{'text-align': 'right'}">{{group[0].total}}/{{threshold.threshold}}</td> <!-- progress -->
|
||||
</ng-container>
|
||||
</tr>
|
||||
</ng-container>
|
||||
<ng-container *ngIf="!threshold.awarded">
|
||||
<tr *ngIf="group.expanded" [ngStyle]="{'background-color': '#F25F5F', 'color': '#ffffff' }">
|
||||
<td class="col-3">{{(medals | keys)[groupIndex]}} {{thresholdIndex + 1}}</td>
|
||||
<td class="col-7">DESCRIPTION</td>
|
||||
<td class="col-2" [ngStyle]="{'text-align': 'right'}">{{group[0].total}}/{{threshold.threshold}}</td> <!-- progress -->
|
||||
</tr>
|
||||
</ng-container>
|
||||
</ng-container>
|
||||
<ng-container *ngIf="(medalList | filterBy: ['title']: groupNo.title: search: true).length == 1"> <!-- if there is only one medal in the group, just display medal, no header -->
|
||||
<ng-container *ngFor="let medal of medalList | orderBy: ['+medalGroupId', '+reward']"> <!-- Unnecessary loop because there is only one medal in each group -->
|
||||
<tr *ngIf="medal.medalGroupId == i && groupNo.medalType == 'global'" [ngStyle]="{'background-color':medal.unlocked === true ? '#89DD73' : '#F25F5F', 'color': '#ffffff' }">
|
||||
<td class="col-3">{{ medal.title }}</td> <!-- medal name -->
|
||||
<td class="col-7">{{ medal.description }}</td> <!-- medal description -->
|
||||
<td class="col-2" [ngStyle]="{'text-align': 'right'}">0/{{ medal.valueRequired }}</td> <!-- progress -->
|
||||
</ng-container>
|
||||
</ng-container>
|
||||
<ng-container *ngIf="(group[0] | values).length - 1 == 1"> <!-- if there is only one medal in the group, just display medal, no header -->
|
||||
<ng-container *ngFor="let threshold of group[0] | values | orderBy: '+threshold'; let thresholdIndex = index">
|
||||
<ng-container *ngIf="threshold | isObject">
|
||||
<tr [ngStyle]="{'background-color':threshold.awarded === true ? '#5FBC47' : '#F25F5F', 'color': '#ffffff' }">
|
||||
<td class="col-3">{{(medals | keys)[groupIndex]}}</td>
|
||||
<td class="col-7">DESCRIPTION</td>
|
||||
<td class="col-2" [ngStyle]="{'text-align': 'right'}">{{group[0].total}}/{{threshold.threshold}}</td> <!-- progress -->
|
||||
</tr>
|
||||
</ng-container>
|
||||
</ng-container>
|
||||
</ng-container>
|
||||
</ng-container>
|
||||
</ng-container> <!-- ngFor each group of medals (global) -->
|
||||
<ng-container *ngFor="let organisation of organisationList | orderBy: '+name'; let orgI = index"> <!-- ngFor organisation of organisationList -->
|
||||
<!-- ngIf organisation is/isn't expanded display correct header -->
|
||||
<tr *ngIf="organisation.expanded" (click)="organisation.expanded = false" [ngStyle]="{'background-color': '#F39C12', 'color': '#ffffff' }">
|
||||
<td class="col-3">{{organisation.name}}</td>
|
||||
<ng-container *ngFor="let medals of organisationMedalList">
|
||||
<ng-container *ngFor="let orgs of medals | values">
|
||||
<ng-container *ngFor="let org of orgs; let orgIndex = index">
|
||||
<tr *ngIf="org.expanded" (click)="org.expanded = false" [ngStyle]="{'background-color': '#F39C12', 'color': '#ffffff' }">
|
||||
<td class="col-3">{{org.name}}</td>
|
||||
<td class="col-6">Click to collapse</td>
|
||||
<td class="col-1">-</td>
|
||||
<td class="col-2" [ngStyle]="{'text-align': 'right'}">{{ (medalList | filterBy: ['medalType']: 'organisation' | filterBy: ['unlocked']: true).length }}/{{ (medalList | filterBy: ['medalType']: 'organisation').length }}</td>
|
||||
<td class="col-2" [ngStyle]="{'text-align': 'right'}">{{org.count}}/{{org.threshold}}</td>
|
||||
</tr>
|
||||
<tr *ngIf="!organisation.expanded" (click)="organisation.expanded = true" [ngStyle]="{'background-color': '#F39C12', 'color': '#ffffff' }">
|
||||
<td class="col-3">{{organisation.name}}</td>
|
||||
<tr *ngIf="!org.expanded" (click)="org.expanded = true" [ngStyle]="{'background-color': '#F39C12', 'color': '#ffffff' }">
|
||||
<td class="col-3">{{org.name}}</td>
|
||||
<td class="col-6">Click to expand</td>
|
||||
<td class="col-1">+</td>
|
||||
<td class="col-2" [ngStyle]="{'text-align': 'right'}">{{ (medalList | filterBy: ['medalType']: 'organisation' | filterBy: ['unlocked']: true).length }}/{{ (medalList | filterBy: ['medalType']: 'organisation').length }}</td>
|
||||
<td class="col-2" [ngStyle]="{'text-align': 'right'}">{{org.count}}/{{org.threshold}}</td>
|
||||
</tr>
|
||||
<ng-container *ngFor="let groupNo of medalList | unique: 'medalGroupId'; let i = index"> <!-- ngFor each group of medals (organisation) -->
|
||||
<ng-container *ngIf="(medalList | filterBy: ['title']: groupNo.title: search: true).length > 1"> <!-- ngIf length of group is more than 1 -->
|
||||
<!-- ngIf organisation is/isn't expanded -->
|
||||
<tr *ngIf="organisation.expanded && groupNo.expanded && groupNo.medalType == 'organisation'" (click)="groupNo.expanded = false" [ngStyle]="{'background-color': '#20A8D8', 'color': '#ffffff' }">
|
||||
<td class="col-3">{{groupNo.title}}</td>
|
||||
<ng-container *ngFor="let group of org | values; let groupIndex = index">
|
||||
<ng-container *ngIf="group | isObject">
|
||||
<ng-container *ngIf="(group[0] | keys).length - 1 > 1">
|
||||
<tr *ngIf="group.expanded && org.expanded" (click)="group.expanded = false" [ngStyle]="{'background-color': '#20A8D8', 'color': '#ffffff' }">
|
||||
<td class="col-3">{{(org | keys)[groupIndex]}}</td>
|
||||
<td class="col-6">Click to collapse</td>
|
||||
<td class="col-1">-</td>
|
||||
<td class="col-2" [ngStyle]="{'text-align': 'right'}">{{ ((medalList | filterBy: ['medalType']: 'organisation' | filterBy: ['title']: groupNo.title: search: true) | filterBy: ['unlocked']: true).length }}/{{ (medalList | filterBy: ['medalType']: 'organisation'| filterBy: ['title']: groupNo.title: search: true).length }}</td>
|
||||
<td class="col-2" [ngStyle]="{'text-align': 'right'}">{{(group[0] | values | filterBy: ['awarded']: 'true' | pluck: 'awarded').length}}/{{(group[0] | values | filterBy: ['awarded']).length}}</td>
|
||||
</tr>
|
||||
<tr *ngIf="organisation.expanded && !groupNo.expanded && groupNo.medalType == 'organisation'" (click)="groupNo.expanded = true" [ngStyle]="{'background-color': '#20A8D8', 'color': '#ffffff' }">
|
||||
<td class="col-3">{{groupNo.title}}</td>
|
||||
<tr *ngIf="!group.expanded && org.expanded" (click)="group.expanded = true" [ngStyle]="{'background-color': '#20A8D8', 'color': '#ffffff' }">
|
||||
<td class="col-3">{{(org | keys)[groupIndex]}}</td>
|
||||
<td class="col-6">Click to expand</td>
|
||||
<td class="col-1">+</td>
|
||||
<td class="col-2" [ngStyle]="{'text-align': 'right'}">{{ ((medalList | filterBy: ['medalType']: 'organisation' | filterBy: ['title']: groupNo.title: search: true) | filterBy: ['unlocked']: true).length }}/{{ (medalList | filterBy: ['medalType']: 'organisation'| filterBy: ['title']: groupNo.title: search: true).length }}</td>
|
||||
<td class="col-2" [ngStyle]="{'text-align': 'right'}">{{(group[0] | values | filterBy: ['awarded']: 'true' | pluck: 'awarded').length}}/{{(group[0] | values | filterBy: ['awarded']).length}}</td>
|
||||
</tr>
|
||||
<ng-container *ngFor="let medal of medalList | orderBy: ['+medalGroupId', '+reward']">
|
||||
<tr *ngIf="organisation.expanded && groupNo.expanded && medal.medalGroupId == i && groupNo.medalType == 'organisation'" [ngStyle]="{'background-color':medal.unlocked === true ? '#89DD73' : '#F25F5F', 'color': '#ffffff' }">
|
||||
<td class="col-3">{{ medal.title }}</td>
|
||||
<td class="col-7">{{ medal.description }}</td>
|
||||
<td class="col-2" [ngStyle]="{'text-align': 'right'}">0/{{ medal.valueRequired }}</td>
|
||||
<ng-container *ngFor="let threshold of group[0] | values | orderBy: '+threshold'; let thresholdIndex = index">
|
||||
<ng-container *ngIf="threshold | isObject">
|
||||
<ng-container *ngIf="threshold.awarded">
|
||||
<tr *ngIf="group.expanded && org.expanded" [ngStyle]="{'background-color': '#5FBC47', 'color': '#ffffff' }">
|
||||
<td class="col-3">{{(org | keys)[groupIndex]}} {{thresholdIndex + 1}}</td>
|
||||
<td class="col-7">DESCRIPTION</td>
|
||||
<ng-container *ngIf="thresholdIndex + 1 != (group[0] | values | orderBy: '+threshold').length - 1">
|
||||
<td class="col-2" [ngStyle]="{'text-align': 'right'}">{{threshold.threshold}}/{{threshold.threshold}}</td>
|
||||
</ng-container>
|
||||
<ng-container *ngIf="thresholdIndex + 1 == (group[0] | values | orderBy: '+threshold').length - 1">
|
||||
<td class="col-2" [ngStyle]="{'text-align': 'right'}">{{group[0].total}}/{{threshold.threshold}}</td>
|
||||
</ng-container>
|
||||
</tr>
|
||||
</ng-container>
|
||||
<ng-container *ngIf="!threshold.awarded">
|
||||
<tr *ngIf="group.expanded && org.expanded" [ngStyle]="{'background-color': '#F25F5F', 'color': '#ffffff' }">
|
||||
<td class="col-3">{{(org | keys)[groupIndex]}} {{thresholdIndex + 1}}</td>
|
||||
<td class="col-7">DESCRIPTION</td>
|
||||
<td class="col-2" [ngStyle]="{'text-align': 'right'}">{{group[0].total}}/{{threshold.threshold}}</td>
|
||||
</tr>
|
||||
</ng-container>
|
||||
</ng-container>
|
||||
<ng-container *ngIf="(medalList | filterBy: ['title']: groupNo.title: search: true).length <= 1"> <!-- ngIf length or group is <= 1 -->
|
||||
<ng-container *ngFor="let medal of medalList | orderBy: ['+medalGroupId', '+reward']">
|
||||
<tr *ngIf="organisation.expanded && medal.medalGroupId == i && groupNo.medalType == 'organisation'" [ngStyle]="{'background-color':medal.unlocked === true ? '#89DD73' : '#F25F5F', 'color': '#ffffff' }">
|
||||
<td class="col-3">{{ medal.title }}</td>
|
||||
<td class="col-7">{{ medal.description }}</td>
|
||||
<td class="col-2" [ngStyle]="{'text-align': 'right'}">0/{{ medal.valueRequired }}</td>
|
||||
</ng-container>
|
||||
</ng-container>
|
||||
<ng-container *ngIf="(group[0] | keys).length - 1 == 1">
|
||||
<ng-container *ngFor="let threshold of group[0] | values | orderBy: '+threshold'; let thresholdIndex = index">
|
||||
<ng-container *ngIf="threshold | isObject">
|
||||
<ng-container *ngIf="org.expanded">
|
||||
<tr [ngStyle]="{'background-color':threshold.awarded === true ? '#5FBC47' : '#F25F5F', 'color': '#ffffff' }">
|
||||
<td class="col-3">{{(org | keys)[groupIndex]}}</td>
|
||||
<td class="col-7">DESCRIPTION</td>
|
||||
<td class="col-2" [ngStyle]="{'text-align': 'right'}">{{group[0].total}}/{{threshold.threshold}}</td>
|
||||
</tr>
|
||||
</ng-container>
|
||||
</ng-container>
|
||||
</ng-container> <!-- ngFor each group of medals (organisation) -->
|
||||
</ng-container> <!-- ngFor organisation of organisationList -->
|
||||
</ng-container>
|
||||
</ng-container>
|
||||
</ng-container>
|
||||
</ng-container>
|
||||
</ng-container>
|
||||
</ng-container>
|
||||
</ng-container>
|
||||
</tbody>
|
||||
</table>
|
||||
</div> <!-- if !noMedalList -->
|
||||
<div *ngIf="noMedalList" class="card-block">
|
||||
<div *ngIf="noGlobalMedalList && noOrganisationMedalList" class="card-block">
|
||||
No Leaderboard available.
|
||||
</div> <!-- if noMedalList -->
|
||||
</div>
|
||||
</div><!-- Row -->
|
||||
<div *ngFor="let group of globalMedalList">
|
||||
<div *ngFor="let threshold of group.group_name | pluck: 'threshold'">
|
||||
</div>
|
||||
</div>
|
||||
<div *ngFor="let medals of testList">
|
||||
<div *ngFor="let group of medals | values; let groupIndex = index">
|
||||
<div>threshold length - total {{(group[0] | values).length - 1}}</div>
|
||||
<div>group_title {{(medals | keys)[groupIndex]}}</div>
|
||||
<div>All awarded values for group {{group[0] | values | filterBy: ['awarded']: 'true' | pluck: 'awarded' | json}}</div>
|
||||
<div *ngFor="let thresholds of group[0] | values">
|
||||
<div *ngIf="thresholds | isObject">
|
||||
<div>9 {{thresholds | json}}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -13,53 +13,34 @@ import 'rxjs/add/operator/map';
|
|||
// import Services
|
||||
import { CustSnippetsService } from '../providers/cust-snippets.service';
|
||||
import { MedalsService } from '../providers/medals.service';
|
||||
//import { HeroPointsStatsService } from '../providers/hero-points-stats.service';
|
||||
import { HeroPointsSnippetsService } from '../providers/hero-points-snippets.service';
|
||||
|
||||
// Pipes
|
||||
import { KeysPipe } from 'ngx-pipes';
|
||||
import { FilterByPipe} from 'ngx-pipes';
|
||||
import { ValuesPipe } from 'ngx-pipes';
|
||||
import { PluckPipe } from 'ngx-pipes';
|
||||
|
||||
@Component({
|
||||
templateUrl: './hero-points.component.html',
|
||||
|
||||
//ngx Pipes
|
||||
providers: [
|
||||
KeysPipe,
|
||||
FilterByPipe,
|
||||
ValuesPipe,
|
||||
PluckPipe,
|
||||
HeroPointsSnippetsService,
|
||||
]
|
||||
})
|
||||
|
||||
|
||||
|
||||
export class HeroPointsComponent implements OnInit {
|
||||
|
||||
order: string = 'heroPoints';
|
||||
|
||||
public testList = [
|
||||
{
|
||||
group_name: [{
|
||||
5: {
|
||||
awarded: true,
|
||||
awarded_at: null,
|
||||
points: 0,
|
||||
threshold: 5,
|
||||
},
|
||||
10: {
|
||||
awarded: true,
|
||||
awarded_at: null,
|
||||
points: 0,
|
||||
threshold: 10,
|
||||
},
|
||||
25: {
|
||||
awarded: false,
|
||||
awarded_at: null,
|
||||
points: 0,
|
||||
threshold: 25,
|
||||
},
|
||||
total: 11,
|
||||
}],
|
||||
group_name2: [{
|
||||
10: {
|
||||
awarded: false,
|
||||
awarded_at: null,
|
||||
points: 0,
|
||||
threshold: 10,
|
||||
},
|
||||
total: 3,
|
||||
}],
|
||||
}
|
||||
]
|
||||
|
||||
public globalMedalList = [
|
||||
{
|
||||
public globalMedalList = [{
|
||||
group_name: [{
|
||||
threshold: {
|
||||
awarded: false,
|
||||
|
@ -69,8 +50,7 @@ export class HeroPointsComponent implements OnInit {
|
|||
},
|
||||
total: 0,
|
||||
}],
|
||||
}
|
||||
]
|
||||
}];
|
||||
|
||||
public organisationMedalList = [{
|
||||
org_id: [{
|
||||
|
@ -84,45 +64,20 @@ export class HeroPointsComponent implements OnInit {
|
|||
total: 0,
|
||||
}],
|
||||
name: '',
|
||||
count: null,
|
||||
threshold: null,
|
||||
}],
|
||||
}]
|
||||
|
||||
public medals = {
|
||||
global: {
|
||||
group_name: {
|
||||
threshold: {
|
||||
awarded: false,
|
||||
awarded_at: "2017-01-01-T00:00:00Z",
|
||||
points: 0,
|
||||
threshold: 0,
|
||||
},
|
||||
total: 0,
|
||||
},
|
||||
},
|
||||
|
||||
organisation: {
|
||||
org_id: {
|
||||
group_name: {
|
||||
threshold: {
|
||||
awarded: false,
|
||||
awarded_at: "2017-01-01-T00:00:00Z",
|
||||
multiplier: 0,
|
||||
points: 0,
|
||||
threshold: 0,
|
||||
},
|
||||
total: 0,
|
||||
},
|
||||
name: "Placeholder",
|
||||
}
|
||||
}
|
||||
};
|
||||
}];
|
||||
|
||||
// Hero points stats
|
||||
public statsThisWeek = 0;
|
||||
public statsLastWeek = 0;
|
||||
public statsMax = 0;
|
||||
public statsSum = 0;
|
||||
public statsCount = 0;
|
||||
public heroPointsStats = {
|
||||
this_week: 0,
|
||||
last_week: 0,
|
||||
max: 0,
|
||||
sum: 0,
|
||||
count: 0,
|
||||
avg: 0,
|
||||
};
|
||||
|
||||
// Gets list of transactions
|
||||
public paginateConfig: PaginationInstance = {
|
||||
|
@ -145,7 +100,11 @@ export class HeroPointsComponent implements OnInit {
|
|||
constructor(
|
||||
private api: ApiService,
|
||||
private medalsService: MedalsService,
|
||||
//private heroPointsStatsService: HeroPointsStatsService,
|
||||
private keysPipe: KeysPipe,
|
||||
private filterByPipe: FilterByPipe,
|
||||
private valuesPipe: ValuesPipe,
|
||||
private pluckPipe: PluckPipe,
|
||||
private heroPointsSnippetsService: HeroPointsSnippetsService,
|
||||
) {
|
||||
this.api.customerStats().subscribe(
|
||||
result => {
|
||||
|
@ -173,19 +132,19 @@ export class HeroPointsComponent implements OnInit {
|
|||
this.setGlobalMedalList(result.global),
|
||||
this.setOrganisationMedalList(result.organisation)
|
||||
}
|
||||
)
|
||||
/*
|
||||
this.heroPointsStatsService.getHeroPointsStats()
|
||||
);
|
||||
|
||||
this.heroPointsSnippetsService.getHeroPointsSnippets()
|
||||
.subscribe(
|
||||
result => {
|
||||
this.statsThisWeek = result.points.stats.this_week;
|
||||
this.statsLastWeek = result.points.stats.last_week;
|
||||
this.statsMax = result.points.stats.max;
|
||||
this.statsSum = result.points.stats.sum;
|
||||
this.statsCount = result.points.stats.count;
|
||||
this.heroPointsStats.this_week = result.widget_progress.this_week;
|
||||
this.heroPointsStats.last_week = result.widget_progress.last_week;
|
||||
this.heroPointsStats.max = result.widget_progress.max;
|
||||
this.heroPointsStats.sum = result.widget_progress.sum;
|
||||
this.heroPointsStats.count = result.widget_progress.count;
|
||||
this.heroPointsStats.avg = result.widget_progress.sum / result.widget_progress.count;
|
||||
}
|
||||
)
|
||||
*/
|
||||
);
|
||||
};
|
||||
|
||||
public setGlobalMedalList( data:any ){
|
||||
|
@ -216,6 +175,8 @@ export class HeroPointsComponent implements OnInit {
|
|||
total: data.org_id.group_name.total,
|
||||
}],
|
||||
name: data.org_id.name,
|
||||
count: (this.pluckPipe.transform(this.filterByPipe.transform(this.valuesPipe.transform(data.org_id.group_name), ['awarded'], true), 'awarded')).length,
|
||||
threshold: (this.filterByPipe.transform(this.valuesPipe.transform(data.org_id.group_name), ['awarded'], true)).length,
|
||||
}],
|
||||
}]
|
||||
};
|
||||
|
|
15
src/app/providers/hero-points-graph.service.ts
Normal file
15
src/app/providers/hero-points-graph.service.ts
Normal file
|
@ -0,0 +1,15 @@
|
|||
import { Injectable } from '@angular/core';
|
||||
import { ApiService } from './api-service';
|
||||
import { Observable } from 'rxjs/Rx';
|
||||
|
||||
@Injectable()
|
||||
export class HeroPointsGraphService {
|
||||
private heroPointsGraphUrl = '/v1/user/points';
|
||||
|
||||
constructor(private api: ApiService) { }
|
||||
|
||||
// This endpoint should mimic basicStats
|
||||
public getHeroPointsGraph(): Observable<any> {
|
||||
return this.api.post(this.heroPointsGraphUrl);
|
||||
}
|
||||
}
|
|
@ -9,7 +9,7 @@ export class HeroPointsSnippetsService {
|
|||
constructor(private api: ApiService) { }
|
||||
|
||||
// This endpoint should mimic basicStats
|
||||
public getPointsData(): Observable<any> {
|
||||
public getHeroPointsSnippets(): Observable<any> {
|
||||
return this.api.post(this.heroPointsSnippetsUrl);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,14 +0,0 @@
|
|||
import { Injectable } from '@angular/core';
|
||||
import { ApiService } from './api-service';
|
||||
import { Observable } from 'rxjs/Rx';
|
||||
|
||||
@Injectable()
|
||||
export class HeroPointsStatsService {
|
||||
private heroPointsStatsUrl = '/v1/user/points';
|
||||
|
||||
constructor(private api: ApiService) { }
|
||||
|
||||
public getHeroPointsStats(): Observable<any> {
|
||||
return this.api.post(this.heroPointsStatsUrl);
|
||||
}
|
||||
}
|
|
@ -10,6 +10,7 @@ export class MedalsService {
|
|||
|
||||
public getMedals(): Observable<any> {
|
||||
return this.api.post(this.medalsUrl);
|
||||
//return Observable.of()
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
<ul style="list-style: none; padding-left: 0;">
|
||||
<li class="hidden-sm-down">
|
||||
<div><h5 class="text-orange">My Hero Points</h5></div>
|
||||
<div class="number-circle-hero mx-auto"><strong>{{ pointTotal | number:'1.0-0' }}</strong></div>
|
||||
<div class="number-circle-hero mx-auto"><strong>{{ heroPointsSnippets.points_total | number:'1.0-0' }}</strong></div>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
@ -17,7 +17,7 @@
|
|||
<ul style="list-style: none; padding-left: 0;">
|
||||
<li class="hidden-sm-down">
|
||||
<div><h5 class="text-dark-green">Last Transaction Points</h5></div>
|
||||
<div class="number-circle mx-auto"><strong>{{pointLast | number:'1.0-0' }}</strong></div>
|
||||
<div class="number-circle mx-auto"><strong>{{ heroPointsSnippets.point_last | number:'1.0-0' }}</strong></div>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
@ -29,7 +29,7 @@
|
|||
<ul style="list-style: none; padding-left: 0;">
|
||||
<li class="hidden-sm-down">
|
||||
<div><h5 class="text-dark-green">Total Transactions</h5></div>
|
||||
<div class="number-circle mx-auto"><strong>{{ transCount | number:'1.0-0' }}</strong></div>
|
||||
<div class="number-circle mx-auto"><strong>{{ heroPointsSnippets.trans_count | number:'1.0-0' }}</strong></div>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
@ -41,7 +41,7 @@
|
|||
<ul style="list-style: none; padding-left: 0;">
|
||||
<li class="hidden-sm-down">
|
||||
<div><h5 class="text-dark-green">Average Multiplier</h5></div>
|
||||
<div class="number-circle mx-auto"><strong>{{ avgMulti | number:'1.0-0' }}</strong></div>
|
||||
<div class="number-circle mx-auto"><strong>{{ heroPointsSnippets.avg_multi | number:'1.0-0' }}</strong></div>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
|
|
@ -8,24 +8,27 @@ import { HeroPointsSnippetsService } from '../providers/hero-points-snippets.ser
|
|||
|
||||
export class HeroPointsSnippetBarComponent implements OnInit {
|
||||
|
||||
public pointTotal = 0;
|
||||
public pointLast = 0;
|
||||
public transCount = 0;
|
||||
public avgMulti = 0;
|
||||
// Hero Points snippets
|
||||
public heroPointsSnippets = {
|
||||
avg_multi: 0,
|
||||
point_last: 0,
|
||||
points_total: 0,
|
||||
trans_count: 0,
|
||||
};
|
||||
|
||||
constructor(
|
||||
private snippetsService: HeroPointsSnippetsService,
|
||||
private heroPointsSnippetsService: HeroPointsSnippetsService,
|
||||
) { }
|
||||
|
||||
public ngOnInit(): void {
|
||||
this.snippetsService.getPointsData()
|
||||
this.heroPointsSnippetsService.getHeroPointsSnippets()
|
||||
.subscribe(
|
||||
result => {
|
||||
this.pointTotal = result.snippets.point_total;
|
||||
this.pointLast = result.snippets.point_last;
|
||||
this.transCount = result.snippets.trans_count;
|
||||
this.avgMulti = result.snippets.avg_multi;
|
||||
this.heroPointsSnippets.avg_multi = result.snippets.avg_multi;
|
||||
this.heroPointsSnippets.point_last = result.snippets.point_last;
|
||||
this.heroPointsSnippets.points_total = result.snippets.points_total;
|
||||
this.heroPointsSnippets.trans_count = result.snippets.trans_count;
|
||||
}
|
||||
);
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
21
src/app/widgets/hero-points-graph-widget.component.html
Normal file
21
src/app/widgets/hero-points-graph-widget.component.html
Normal file
|
@ -0,0 +1,21 @@
|
|||
<div class="card card-inverse card-primary">
|
||||
<div class="card-block pb-0">
|
||||
<button type="button" class="btn btn-transparent p-0 float-right">
|
||||
<i [ngClass]="graphIcon"></i>
|
||||
</button>
|
||||
<h4 *ngIf="dataType == availableDataTypes.number" class="mb-0">{{ graphSum }}</h4>
|
||||
<p>{{ graphTitle }}</p>
|
||||
</div>
|
||||
<div class="chart-wrapper px-3" style="height:70px;">
|
||||
<canvas baseChart
|
||||
class="chart"
|
||||
[datasets]="lineChartData"
|
||||
[labels]="lineChartLabels"
|
||||
[options]="lineChartOptions"
|
||||
[colors]="lineChartColours"
|
||||
[legend]="lineChartLegend"
|
||||
[chartType]="lineChartType"
|
||||
(chartHover)="chartHovered($event)"
|
||||
(chartClick)="chartClicked($event)"></canvas>
|
||||
</div>
|
||||
</div>
|
154
src/app/widgets/hero-points-graph-widget.component.ts
Normal file
154
src/app/widgets/hero-points-graph-widget.component.ts
Normal file
|
@ -0,0 +1,154 @@
|
|||
import { Component, OnInit, Input, Output, EventEmitter } from '@angular/core';
|
||||
import { OrgGraphsService } from '../providers/org-graphs.service';
|
||||
import { DataType } from '../shared/data-types.enum';
|
||||
|
||||
interface ChartData {
|
||||
data: Array<number>;
|
||||
label: string;
|
||||
}
|
||||
|
||||
@Component({
|
||||
selector: 'hero-points-widget-graph',
|
||||
templateUrl: 'hero-points-graph-widget.component.html',
|
||||
})
|
||||
export class HeroPointsGraphWidget implements OnInit {
|
||||
@Input() public graphName: string;
|
||||
@Input() public graphTitle = 'Graph';
|
||||
@Input() public graphIcon = 'icon-graph';
|
||||
@Input() public dataType: DataType = DataType.number;
|
||||
|
||||
@Output() public graphHover = new EventEmitter();
|
||||
@Output() public graphClick = new EventEmitter();
|
||||
|
||||
public graphSum: Number = 0;
|
||||
public availableDataTypes = DataType;
|
||||
|
||||
public lineChartData: Array<ChartData> = [
|
||||
{
|
||||
data: [],
|
||||
label: 'Series A'
|
||||
}
|
||||
];
|
||||
public lineChartLabels: Array<string>;
|
||||
public lineChartOptions: any = {
|
||||
maintainAspectRatio: false,
|
||||
scales: {
|
||||
xAxes: [{
|
||||
type: 'time',
|
||||
time: {
|
||||
unit: 'day',
|
||||
displayFormats: {
|
||||
day: 'MMM D',
|
||||
},
|
||||
tooltipFormat: 'MMM D',
|
||||
},
|
||||
gridLines: {
|
||||
color: 'transparent',
|
||||
zeroLineColor: 'transparent'
|
||||
},
|
||||
ticks: {
|
||||
fontSize: 2,
|
||||
source: 'data',
|
||||
fontColor: 'transparent',
|
||||
}
|
||||
|
||||
}],
|
||||
yAxes: [{
|
||||
display: false,
|
||||
ticks: {
|
||||
display: false,
|
||||
}
|
||||
}],
|
||||
},
|
||||
elements: {
|
||||
line: {
|
||||
borderWidth: 1
|
||||
},
|
||||
point: {
|
||||
radius: 4,
|
||||
hitRadius: 10,
|
||||
hoverRadius: 4,
|
||||
},
|
||||
},
|
||||
legend: {
|
||||
display: false
|
||||
},
|
||||
tooltips: {
|
||||
callbacks: {
|
||||
label: (tooltip, data) => {
|
||||
return this.tooltipLabelCallback(tooltip, data);
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
public lineChartColours: Array<any> = [
|
||||
{
|
||||
backgroundColor: '#20a8d8',
|
||||
borderColor: 'rgba(255,255,255,.55)'
|
||||
}
|
||||
];
|
||||
public lineChartLegend = false;
|
||||
public lineChartType = 'line';
|
||||
|
||||
|
||||
constructor(
|
||||
private graphService: OrgGraphsService,
|
||||
) { }
|
||||
|
||||
ngOnInit(): void {
|
||||
if ( this.graphName == null ) {
|
||||
throw new Error('Attribute \'graphName\' is required on component \'widget-graph\'');
|
||||
}
|
||||
if ( this.dataType === undefined ) {
|
||||
// Need to do this as it may be passed in a loop with an undefined value
|
||||
this.dataType = DataType.number;
|
||||
}
|
||||
if ( !( this.dataType in DataType ) ) {
|
||||
console.warn('Unknown DataType for graph \'' + this.graphName + '\' - defaulting to number');
|
||||
}
|
||||
this.graphService.getGraph(this.graphName)
|
||||
.subscribe( result => this.setData(result.graph) );
|
||||
}
|
||||
|
||||
private setData(data: any) {
|
||||
this.setChartData(data.data);
|
||||
this.setChartLabels(data.labels);
|
||||
this.setChartBounds(data.bounds);
|
||||
}
|
||||
|
||||
private setChartBounds(data) {
|
||||
this.lineChartOptions.scales.xAxes[0].time.max = data.max;
|
||||
this.lineChartOptions.scales.xAxes[0].time.min = data.min;
|
||||
}
|
||||
|
||||
private setChartData(data: Array<number>) {
|
||||
this.lineChartData[0].data = data;
|
||||
this.graphSum = data.reduce((a, b) => a + b, 0);
|
||||
// Set point size based on data
|
||||
if ( data.length < 15 ) {
|
||||
this.lineChartOptions.elements.point.radius = 4;
|
||||
this.lineChartOptions.elements.line.borderWidth = 1;
|
||||
} else {
|
||||
this.lineChartOptions.elements.point.radius = 2;
|
||||
this.lineChartOptions.elements.line.borderWidth = 2;
|
||||
}
|
||||
}
|
||||
|
||||
private setChartLabels(data: Array<string>) {
|
||||
this.lineChartLabels = data;
|
||||
}
|
||||
|
||||
// events
|
||||
public chartClicked(e: any): void {
|
||||
console.log(e);
|
||||
}
|
||||
|
||||
public chartHovered(e: any): void {
|
||||
console.log(e);
|
||||
}
|
||||
|
||||
private tooltipLabelCallback(tooltipItem: any, data: any) {
|
||||
const value = tooltipItem.yLabel;
|
||||
return value || '0';
|
||||
}
|
||||
}
|
Reference in a new issue