<!doctype html>
<html>
<head>
<script src="./lib/main.ts"></script>
<link rel="stylesheet" href="https://cdn.linearicons.com/free/1.0.0/icon-font.min.css">
</head>
<body>
<my-app>
loading...
</my-app>
</body>
</html>
//our root app component
import { Component, NgModule, VERSION } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import {UsageGaugeComponent} from './gauge.component'
@Component({
selector: 'my-app',
template: `
<div>
<h1>Horizontal Gauge with CSS</h1>
<div class="row">
<div class="col-md-9">
<div class="mt-5 mb-5">
<usage-gauge></usage-gauge>
</div>
</div>
</div>
</div>
`,
})
export class App {
name: string;
constructor() {
this.name = `Angular! v${VERSION.full}`;
}
}
@NgModule({
imports: [BrowserModule],
declarations: [App, UsageGaugeComponent],
bootstrap: [App],
})
export class AppModule {}
// Shim the environment
import 'core-js/client/shim';
// Angular requires Zones to be pre-configured in the environment
import 'zone.js/dist/zone';
//main entry point
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
import { AppModule } from './app';
import './style.css';
platformBrowserDynamic().bootstrapModule(AppModule);
h1,
p {
font-family: sans-serif;
}
import { Component, Input, OnInit } from '@angular/core';
import {ConversionUtils} from './ConversionUtils'
@Component({
selector: 'usage-gauge',
template: `
<div class="gauge-bar-graph">
<div [style.width.%]=currentUsageVal [ngClass]="[usagePointerColour + ' usage-bar']"><span>{{usageLabelValue}}</span></div>
<div *ngIf="alert != 0" [style.left.%]="alert" class="bar-1"><div class="pointer alert-pointer">{{alertLabelValue}}</div></div>
<div *ngIf="cap != 0" [style.left.%]="cap" class="bar-2"><div class="pointer cap-pointer">{{capLabelValue}}</div></div>
</div>
`,
styles: [`
:host{
width:100%;
display:block;
}
.gauge-bar-graph {
position: relative;
width: 100%;
height:30px;
border-bottom:1px solid grey;
display:block;
}
.value{
position:absolute;
top:50px;
}
.usage-bar{
height: 25px;
position: absolute;
top: 8%;
}
.usage-bar span{
position: absolute;
right: 0;
font-size: .8em;
color: #fff;
}
.pointer {
bottom: -26px;
left:-5px;
position: absolute;
font-size: .8em;
}
.pointer.alert-pointer {
color:orange;
}
.pointer.cap-pointer {
color:red;
}
.bar-1 {
display: inline-block;
position:absolute;
height:100%;
width:1px;
bottom:0;
padding:0;
background-color:orange;
color:orange;
transition: all 1s ease-out;
}
.bar-2 {
display: inline-block;
position:absolute;
height:100%;
width:1px;
bottom:0;
padding:0;
background-color:red;
transition: all 1s ease-out;
}
.usage-bar.normal{
background-color:#7ac943;
}
.usage-bar.alerted{
background-image: linear-gradient(to right, #7ac943 75%, orange 100% );
}
.usage-bar.overage{
background-image: linear-gradient(to right, #7ac943 60%, orange 90%, red 100%);
}
`]
})
export class UsageGaugeComponent implements OnInit {
data = {
alertLimit: 96000,
capLimit: 120000,
usage: 121000,
};
currentUsageVal: number;
usagePointerColour: string;
alert: number = 0;
cap: number = 0;
alertLabelValue: string;
capLabelValue: string;
usageLabelValue: string;
constructor() {}
ngOnInit(): void {
this.getUsageBarCalc(this.data);
}
getUsageBarCalc = (usage): void => {
this.alertLabelValue = ConversionUtils.bytesToMegabytes(usage.alertLimit).toFixed(2);
this.capLabelValue = ConversionUtils.bytesToMegabytes(usage.capLimit).toFixed(2);
this.usageLabelValue = ConversionUtils.bytesToMegabytes(usage.usage).toFixed(2);
if (usage.usage >= 0 && usage.alertLimit > 0 && usage.capLimit > 0) {
if (
usage.usage < usage.alertLimit ||
usage.usage < usage.capLimit
) {
this.calculateGraphAreaOnCapAsBase(
usage,
usage.capLimit * 1.1,
'normal'
);
}
if (
usage.usage >= usage.alertLimit &&
usage.usage < usage.capLimit
) {
this.calculateGraphAreaOnCapAsBase(
usage,
usage.capLimit * 1.1,
'alerted'
);
}
if (usage.usage >= usage.capLimit) {
this.calculateGraphAreaOnUsageAsBase(
usage,
usage.usage * 1.1,
'overage'
);
}
} else if (
usage.capLimit === 0 &&
(usage.usage > 0 && usage.alertLimit > 0)
) {
if (usage.usage >= usage.alertLimit) {
this.calculateGraphAreaOnUsageAsBase(
usage,
usage.usage * 1.1,
'alerted'
);
} else {
this.calculateGraphAreaOnAlertAsBase(
usage,
usage.alertLimit * 1.1,
'normal'
);
}
} else if (
usage.alertLimit === 0 &&
(usage.usage > 0 && usage.capLimit > 0)
) {
if (usage.usage >= usage.capLimit) {
this.calculateGraphAreaOnUsageAsBase(
usage,
usage.usage * 1.1,
'overage'
);
} else {
this.calculateGraphAreaOnCapAsBase(
usage,
usage.capLimit * 1.1,
'normal'
);
}
}
};
calculateGraphAreaOnCapAsBase(
usage,
currentUsageBaseVal: number,
color: string
) {
this.alert = (usage.alertLimit / currentUsageBaseVal) * 100;
this.cap = (usage.capLimit / currentUsageBaseVal) * 100;
this.setUsagePointerAndColor(usage.usage, currentUsageBaseVal, color);
}
calculateGraphAreaOnAlertAsBase(
usage,
currentUsageBaseVal: number,
color: string
) {
this.alert = (usage.alertLimit / currentUsageBaseVal) * 100;
this.cap = 0;
this.setUsagePointerAndColor(usage.usage, currentUsageBaseVal, color);
}
calculateGraphAreaOnUsageAsBase(
usage,
currentUsageBaseVal: number,
color: string
) {
this.alert = (usage.alertLimit / currentUsageBaseVal) * 100;
this.cap = (usage.capLimit / currentUsageBaseVal) * 100;
this.setUsagePointerAndColor(usage.usage, currentUsageBaseVal, color);
}
setUsagePointerAndColor(
usage: number,
currentUsageBaseVal: number,
color: string
) {
this.currentUsageVal = (usage / currentUsageBaseVal) * 100;
this.usagePointerColour = color;
}
}
:host{
width:100%;
display:block;
}
.gauge-bar-graph {
position: relative;
width: 100%;
height:30px;
border-bottom:1px solid grey;
display:block;
}
.value{
position:absolute;
top:50px;
}
.usage-bar{
height: 25px;
position: absolute;
top: 8%;
}
.usage-bar span{
position: absolute;
right: 0;
font-size: .8em;
color: #fff;
}
.pointer {
bottom: -26px;
left:-5px;
position: absolute;
font-size: .8em;
}
.pointer.alert-pointer {
color:orange;
}
.pointer.cap-pointer {
color:red;
}
.bar-1 {
display: inline-block;
position:absolute;
height:100%;
width:1px;
bottom:0;
padding:0;
background-color:orange;
color:orange;
transition: all 1s ease-out;
}
.bar-2 {
display: inline-block;
position:absolute;
height:100%;
width:1px;
bottom:0;
padding:0;
background-color:red;
transition: all 1s ease-out;
}
.usage-bar.normal{
background-color:#7ac943;
}
.usage-bar.alerted{
background-image: linear-gradient(to right, #7ac943 75%, orange 100% );
}
.usage-bar.overage{
background-image: linear-gradient(to right, #7ac943 60%, orange 90%, red 100%);
}
export class ConversionUtils {
public static byteToKiloByte = (bytes: number): number => {
return ConversionUtils.roundTo2DecimalPlaces(bytes / 1024 );
}
public static bytesToMegabytes = (bytes: number): number => {
return ConversionUtils.roundTo2DecimalPlaces( bytes / (1024 * 1024) );
}
public static roundTo2DecimalPlaces = (value: number): number => {
return Math.round(value * 100 ) / 100;
}
}
{
"name": "@plnkr/starter-angular",
"version": "1.0.3",
"description": "Angular starter template",
"dependencies": {
"@angular/common": "^6.0.9",
"@angular/compiler": "^6.0.9",
"@angular/core": "^6.0.9",
"@angular/platform-browser": "^6.0.9",
"@angular/platform-browser-dynamic": "^6.0.9",
"core-js": "^2.5.5",
"rxjs": "^6.1.0",
"zone.js": "^0.8.26"
},
"main": "./lib/main.ts",
"plnkr": {
"runtime": "system",
"useHotReload": true
}
}
{
"compilerOptions": {
"experimentalDecorators": true
}
}