web/storagenode: chart point's hit radius extended

Change-Id: Ib231d7970b4fe9e196638d3a09d2ae96e6c4efc5
This commit is contained in:
VitaliiShpital 2019-12-27 14:16:44 +02:00 committed by Vitalii Shpital
parent d3fe122d9b
commit ae3eae31dc
6 changed files with 255 additions and 260 deletions

View File

@ -20,6 +20,7 @@ import { Component, Vue } from 'vue-property-decorator';
import VChart from '@/app/components/VChart.vue';
import { ChartData } from '@/app/types/chartData';
import { Tooltip, TooltipParams } from '@/app/types/tooltip';
import { ChartUtils } from '@/app/utils/chart';
import { formatBytes } from '@/app/utils/converter';
import { BandwidthUsed } from '@/storagenode/satellite';
@ -51,9 +52,6 @@ class BandwidthTooltip {
},
})
export default class BandwidthChart extends Vue {
private readonly TOOLTIP_OPACITY: string = '1';
private readonly TOOLTIP_POSITION: string = 'absolute';
private get allBandwidth(): BandwidthUsed[] {
return ChartUtils.populateEmptyBandwidth(this.$store.state.node.bandwidthChartData);
}
@ -82,79 +80,45 @@ export default class BandwidthChart extends Vue {
return new ChartData(daysCount, chartBackgroundColor, chartBorderColor, chartBorderWidth, data);
}
public bandwidthTooltip(tooltipModel): void {
// Tooltip Element
let tooltipEl = document.getElementById('bandwidth-tooltip');
// Create element on first render
if (!tooltipEl) {
tooltipEl = document.createElement('div');
tooltipEl.id = 'bandwidth-tooltip';
document.body.appendChild(tooltipEl);
public bandwidthTooltip(tooltipModel: any): void {
const tooltipParams = new TooltipParams(tooltipModel, 'bandwidth-chart', 'bandwidth-tooltip',
'bandwidth-tooltip-arrow', 'bandwidth-tooltip-point', this.tooltipMarkUp(tooltipModel),
303, 125, 35, 24, 6, 4, `#1f49a3`);
Tooltip.custom(tooltipParams);
}
private tooltipMarkUp(tooltipModel: any): string {
if (!tooltipModel.dataPoints) {
return '';
}
// Tooltip Arrow
let tooltipArrow = document.getElementById('bandwidth-tooltip-arrow');
// Create element on first render
if (!tooltipArrow) {
tooltipArrow = document.createElement('div');
tooltipArrow.id = 'bandwidth-tooltip-arrow';
document.body.appendChild(tooltipArrow);
}
const dataIndex = tooltipModel.dataPoints[0].index;
const dataPoint = new BandwidthTooltip(this.allBandwidth[dataIndex]);
// Hide if no tooltip
if (!tooltipModel.opacity) {
document.body.removeChild(tooltipEl);
document.body.removeChild(tooltipArrow);
return;
}
// Set Text
if (tooltipModel.body) {
const dataIndex = tooltipModel.dataPoints[0].index;
const dataPoint = new BandwidthTooltip(this.allBandwidth[dataIndex]);
tooltipEl.innerHTML = `<div class='tooltip-header'>
<p>EGRESS</p>
<p class='tooltip-header__ingress'>INGRESS</p>
</div>
<div class='tooltip-body'>
<div class='tooltip-body__info'>
<p>USAGE</p>
<p class='tooltip-body__info__egress-value'><b class="tooltip-bold-text">${dataPoint.normalEgress}</b></p>
<p class='tooltip-body__info__ingress-value'><b class="tooltip-bold-text">${dataPoint.normalIngress}</b></p>
</div>
<div class='tooltip-body__info'>
<p>REPAIR</p>
<p class='tooltip-body__info__egress-value'><b class="tooltip-bold-text">${dataPoint.repairEgress}</b></p>
<p class='tooltip-body__info__ingress-value'><b class="tooltip-bold-text">${dataPoint.repairIngress}</b></p>
</div>
<div class='tooltip-body__info'>
<p>AUDIT</p>
<p class='tooltip-body__info__egress-value'><b class="tooltip-bold-text">${dataPoint.auditEgress}</b></p>
</div>
</div>
<div class='tooltip-footer'>
<p>${dataPoint.date}</p>
</div>`;
}
const bandwidthChart = document.getElementById('bandwidth-chart');
if (!bandwidthChart) {
return;
}
// `this` will be the overall tooltip.
const position = bandwidthChart.getBoundingClientRect();
tooltipEl.style.opacity = this.TOOLTIP_OPACITY;
tooltipEl.style.position = this.TOOLTIP_POSITION;
tooltipEl.style.left = `${position.left + tooltipModel.caretX - 125}px`;
tooltipEl.style.top = `${position.top + window.pageYOffset + tooltipModel.caretY - 303}px`;
tooltipArrow.style.opacity = this.TOOLTIP_OPACITY;
tooltipArrow.style.position = this.TOOLTIP_POSITION;
tooltipArrow.style.left = `${position.left + tooltipModel.caretX - 24}px`;
tooltipArrow.style.top = `${position.top + window.pageYOffset + tooltipModel.caretY - 35}px`;
return `<div class='tooltip-header'>
<p>EGRESS</p>
<p class='tooltip-header__ingress'>INGRESS</p>
</div>
<div class='tooltip-body'>
<div class='tooltip-body__info'>
<p>USAGE</p>
<p class='tooltip-body__info__egress-value'><b class="tooltip-bold-text">${dataPoint.normalEgress}</b></p>
<p class='tooltip-body__info__ingress-value'><b class="tooltip-bold-text">${dataPoint.normalIngress}</b></p>
</div>
<div class='tooltip-body__info'>
<p>REPAIR</p>
<p class='tooltip-body__info__egress-value'><b class="tooltip-bold-text">${dataPoint.repairEgress}</b></p>
<p class='tooltip-body__info__ingress-value'><b class="tooltip-bold-text">${dataPoint.repairIngress}</b></p>
</div>
<div class='tooltip-body__info'>
<p>AUDIT</p>
<p class='tooltip-body__info__egress-value'><b class="tooltip-bold-text">${dataPoint.auditEgress}</b></p>
</div>
</div>
<div class='tooltip-footer'>
<p>${dataPoint.date}</p>
</div>`;
}
}
</script>

View File

@ -20,6 +20,7 @@ import { Component, Vue } from 'vue-property-decorator';
import VChart from '@/app/components/VChart.vue';
import { ChartData } from '@/app/types/chartData';
import { Tooltip, TooltipParams } from '@/app/types/tooltip';
import { ChartUtils } from '@/app/utils/chart';
import { formatBytes } from '@/app/utils/converter';
import { Stamp } from '@/storagenode/satellite';
@ -43,9 +44,6 @@ class StampTooltip {
},
})
export default class DiskSpaceChart extends Vue {
private readonly TOOLTIP_OPACITY: string = '1';
private readonly TOOLTIP_POSITION: string = 'absolute';
private get allStamps(): Stamp[] {
return ChartUtils.populateEmptyStamps(this.$store.state.node.storageChartData);
}
@ -75,59 +73,25 @@ export default class DiskSpaceChart extends Vue {
}
public diskSpaceTooltip(tooltipModel): void {
// Tooltip Element
let tooltipEl = document.getElementById('disk-space-tooltip');
// Create element on first render
if (!tooltipEl) {
tooltipEl = document.createElement('div');
tooltipEl.id = 'disk-space-tooltip';
document.body.appendChild(tooltipEl);
const tooltipParams = new TooltipParams(tooltipModel, 'disk-space-chart', 'disk-space-tooltip',
'disk-space-tooltip-arrow', 'disk-space-tooltip-point', this.tooltipMarkUp(tooltipModel),
125, 89, 38, 24, 6, 4, `#1f49a3`);
Tooltip.custom(tooltipParams);
}
private tooltipMarkUp(tooltipModel: any): string {
if (!tooltipModel.dataPoints) {
return '';
}
// Tooltip Arrow
let tooltipArrow = document.getElementById('disk-space-tooltip-arrow');
// Create element on first render
if (!tooltipArrow) {
tooltipArrow = document.createElement('div');
tooltipArrow.id = 'disk-space-tooltip-arrow';
document.body.appendChild(tooltipArrow);
}
const dataIndex = tooltipModel.dataPoints[0].index;
const dataPoint = new StampTooltip(this.allStamps[dataIndex]);
// Hide if no tooltip
if (!tooltipModel.opacity) {
document.body.removeChild(tooltipEl);
document.body.removeChild(tooltipArrow);
return;
}
// Set Text
if (tooltipModel.body) {
const dataIndex = tooltipModel.dataPoints[0].index;
const dataPoint = new StampTooltip(this.allStamps[dataIndex]);
tooltipEl.innerHTML = `<div class='tooltip-body'>
<p class='tooltip-body__data'><b>${dataPoint.atRestTotal}*h</b></p>
<p class='tooltip-body__footer'>${dataPoint.date}</p>
</div>`;
}
const diskSpaceChart = document.getElementById('disk-space-chart');
if (!diskSpaceChart) {
return;
}
// `this` will be the overall tooltip.
const position = diskSpaceChart.getBoundingClientRect();
tooltipEl.style.opacity = this.TOOLTIP_OPACITY;
tooltipEl.style.position = this.TOOLTIP_POSITION;
tooltipEl.style.left = `${position.left + tooltipModel.caretX - 89}px`;
tooltipEl.style.top = `${position.top + window.pageYOffset + tooltipModel.caretY - 125}px`;
tooltipArrow.style.opacity = this.TOOLTIP_OPACITY;
tooltipArrow.style.position = this.TOOLTIP_POSITION;
tooltipArrow.style.left = `${position.left + tooltipModel.caretX - 24}px`;
tooltipArrow.style.top = `${position.top + window.pageYOffset + tooltipModel.caretY - 38}px`;
return `<div class='tooltip-body'>
<p class='tooltip-body__data'><b>${dataPoint.atRestTotal}*h</b></p>
<p class='tooltip-body__footer'>${dataPoint.date}</p>
</div>`;
}
}
</script>

View File

@ -20,6 +20,7 @@ import { Component, Vue } from 'vue-property-decorator';
import VChart from '@/app/components/VChart.vue';
import { ChartData } from '@/app/types/chartData';
import { Tooltip, TooltipParams } from '@/app/types/tooltip';
import { ChartUtils } from '@/app/utils/chart';
import { formatBytes } from '@/app/utils/converter';
import { EgressUsed } from '@/storagenode/satellite';
@ -47,9 +48,6 @@ class EgressTooltip {
},
})
export default class EgressChart extends Vue {
private readonly TOOLTIP_OPACITY: string = '1';
private readonly TOOLTIP_POSITION: string = 'absolute';
private get allBandwidth(): EgressUsed[] {
return ChartUtils.populateEmptyBandwidth(this.$store.state.node.egressChartData);
}
@ -79,73 +77,38 @@ export default class EgressChart extends Vue {
}
public egressTooltip(tooltipModel): void {
// Tooltip Element
let tooltipEl = document.getElementById('egress-tooltip');
// Create element on first render
if (!tooltipEl) {
tooltipEl = document.createElement('div');
tooltipEl.id = 'egress-tooltip';
document.body.appendChild(tooltipEl);
const tooltipParams = new TooltipParams(tooltipModel, 'egress-chart', 'egress-tooltip',
'egress-tooltip-arrow', 'egress-tooltip-point', this.tooltipMarkUp(tooltipModel),
255, 94, 35, 24, 6, 4, `#48a77f`);
Tooltip.custom(tooltipParams);
}
private tooltipMarkUp(tooltipModel: any): string {
if (!tooltipModel.dataPoints) {
return '';
}
// Tooltip Arrow
let tooltipArrow = document.getElementById('egress-tooltip-arrow');
// Create element on first render
if (!tooltipArrow) {
tooltipArrow = document.createElement('div');
tooltipArrow.id = 'egress-tooltip-arrow';
document.body.appendChild(tooltipArrow);
}
const dataIndex = tooltipModel.dataPoints[0].index;
const dataPoint = new EgressTooltip(this.allBandwidth[dataIndex]);
// Hide if no tooltip
if (!tooltipModel.opacity) {
document.body.removeChild(tooltipEl);
document.body.removeChild(tooltipArrow);
return;
}
// Set Text
if (tooltipModel.body) {
const dataIndex = tooltipModel.dataPoints[0].index;
const dataPoint = new EgressTooltip(this.allBandwidth[dataIndex]);
tooltipEl.innerHTML = `<div class='egress-tooltip-body'>
<div class='egress-tooltip-body__info'>
<p>USAGE</p>
<b class="egress-tooltip-bold-text">${dataPoint.normalEgress}</b>
</div>
<div class='egress-tooltip-body__info'>
<p>REPAIR</p>
<b class="egress-tooltip-bold-text">${dataPoint.repairEgress}</b>
</div>
<div class='egress-tooltip-body__info'>
<p>AUDIT</p>
<b class="egress-tooltip-bold-text">${dataPoint.auditEgress}</b>
</div>
</div>
<div class='egress-tooltip-footer'>
<p>${dataPoint.date}</p>
</div>`;
}
const egressChart = document.getElementById('egress-chart');
if (!egressChart) {
return;
}
// `this` will be the overall tooltip.
const position = egressChart.getBoundingClientRect();
tooltipEl.style.opacity = this.TOOLTIP_OPACITY;
tooltipEl.style.position = this.TOOLTIP_POSITION;
tooltipEl.style.left = `${position.left + tooltipModel.caretX - 94}px`;
tooltipEl.style.top = `${position.top + window.pageYOffset + tooltipModel.caretY - 255}px`;
tooltipArrow.style.opacity = this.TOOLTIP_OPACITY;
tooltipArrow.style.position = this.TOOLTIP_POSITION;
tooltipArrow.style.left = `${position.left + tooltipModel.caretX - 24}px`;
tooltipArrow.style.top = `${position.top + window.pageYOffset + tooltipModel.caretY - 35}px`;
return `<div class='egress-tooltip-body'>
<div class='egress-tooltip-body__info'>
<p>USAGE</p>
<b class="egress-tooltip-bold-text">${dataPoint.normalEgress}</b>
</div>
<div class='egress-tooltip-body__info'>
<p>REPAIR</p>
<b class="egress-tooltip-bold-text">${dataPoint.repairEgress}</b>
</div>
<div class='egress-tooltip-body__info'>
<p>AUDIT</p>
<b class="egress-tooltip-bold-text">${dataPoint.auditEgress}</b>
</div>
</div>
<div class='egress-tooltip-footer'>
<p>${dataPoint.date}</p>
</div>`;
}
}
</script>
@ -204,7 +167,6 @@ export default class EgressChart extends Vue {
}
.egress-tooltip-bold-text {
font-family: 'font_bold', sans-serif;
font-size: 14px;
}

View File

@ -20,6 +20,7 @@ import { Component, Vue } from 'vue-property-decorator';
import VChart from '@/app/components/VChart.vue';
import { ChartData } from '@/app/types/chartData';
import { Tooltip, TooltipParams } from '@/app/types/tooltip';
import { ChartUtils } from '@/app/utils/chart';
import { formatBytes } from '@/app/utils/converter';
import { IngressUsed } from '@/storagenode/satellite';
@ -45,9 +46,6 @@ class IngressTooltip {
},
})
export default class IngressChart extends Vue {
private readonly TOOLTIP_OPACITY: string = '1';
private readonly TOOLTIP_POSITION: string = 'absolute';
private get allBandwidth(): IngressUsed[] {
return ChartUtils.populateEmptyBandwidth(this.$store.state.node.ingressChartData);
}
@ -77,68 +75,34 @@ export default class IngressChart extends Vue {
}
public ingressTooltip(tooltipModel): void {
// Tooltip Element
let tooltipEl = document.getElementById('ingress-tooltip');
// Create element on first render
if (!tooltipEl) {
tooltipEl = document.createElement('div');
tooltipEl.id = 'ingress-tooltip';
document.body.appendChild(tooltipEl);
const tooltipParams = new TooltipParams(tooltipModel, 'ingress-chart', 'ingress-tooltip',
'ingress-tooltip-arrow', 'ingress-tooltip-point', this.tooltipMarkUp(tooltipModel),
205, 94, 35, 24, 6, 4, `#e1a128`);
Tooltip.custom(tooltipParams);
}
private tooltipMarkUp(tooltipModel: any): string {
if (!tooltipModel.dataPoints) {
return '';
}
// Tooltip Arrow
let tooltipArrow = document.getElementById('ingress-tooltip-arrow');
// Create element on first render
if (!tooltipArrow) {
tooltipArrow = document.createElement('div');
tooltipArrow.id = 'ingress-tooltip-arrow';
document.body.appendChild(tooltipArrow);
}
const dataIndex = tooltipModel.dataPoints[0].index;
const dataPoint = new IngressTooltip(this.allBandwidth[dataIndex]);
// Hide if no tooltip
if (!tooltipModel.opacity) {
document.body.removeChild(tooltipEl);
document.body.removeChild(tooltipArrow);
return;
}
// Set Text
if (tooltipModel.body) {
const dataIndex = tooltipModel.dataPoints[0].index;
const dataPoint = new IngressTooltip(this.allBandwidth[dataIndex]);
tooltipEl.innerHTML = `<div class='ingress-tooltip-body'>
<div class='ingress-tooltip-body__info'>
<p>USAGE</p>
<b class="ingress-tooltip-bold-text">${dataPoint.normalIngress}</b>
</div>
<div class='ingress-tooltip-body__info'>
<p>REPAIR</p>
<b class="ingress-tooltip-bold-text">${dataPoint.repairIngress}</b>
</div>
</div>
<div class='ingress-tooltip-footer'>
<p>${dataPoint.date}</p>
</div>`;
}
const ingressChart = document.getElementById('ingress-chart');
if (!ingressChart) {
return;
}
// `this` will be the overall tooltip.
const position = ingressChart.getBoundingClientRect();
tooltipEl.style.opacity = this.TOOLTIP_OPACITY;
tooltipEl.style.position = this.TOOLTIP_POSITION;
tooltipEl.style.left = `${position.left + tooltipModel.caretX - 94}px`;
tooltipEl.style.top = `${position.top + window.pageYOffset + tooltipModel.caretY - 205}px`;
tooltipArrow.style.opacity = this.TOOLTIP_OPACITY;
tooltipArrow.style.position = this.TOOLTIP_POSITION;
tooltipArrow.style.left = `${position.left + tooltipModel.caretX - 24}px`;
tooltipArrow.style.top = `${position.top + window.pageYOffset + tooltipModel.caretY - 35}px`;
return `<div class='ingress-tooltip-body'>
<div class='ingress-tooltip-body__info'>
<p>USAGE</p>
<b class="ingress-tooltip-bold-text">${dataPoint.normalIngress}</b>
</div>
<div class='ingress-tooltip-body__info'>
<p>REPAIR</p>
<b class="ingress-tooltip-bold-text">${dataPoint.repairIngress}</b>
</div>
</div>
<div class='ingress-tooltip-footer'>
<p>${dataPoint.date}</p>
</div>`;
}
}
</script>
@ -197,7 +161,6 @@ export default class IngressChart extends Vue {
}
.ingress-tooltip-bold-text {
font-family: 'font_bold', sans-serif;
font-size: 14px;
}

View File

@ -69,9 +69,8 @@ export default class VChart extends Vue {
elements: {
point: {
radius: 0,
hitRadius: 5,
hoverRadius: 3,
hoverBorderWidth: 7,
hoverRadius: 0,
hitRadius: 500,
}
},

View File

@ -0,0 +1,143 @@
// Copyright (C) 2019 Storj Labs, Inc.
// See LICENSE for copying information.
/**
* StylingConstants holds tooltip styling constants
*/
class StylingConstants {
public static tooltipOpacity = '1';
public static tooltipPosition = 'absolute';
public static pointWidth = '10px';
public static pointHeight = '10px';
public static borderRadius = '20px';
}
/**
* Styling holds tooltip's styling configuration
*/
class Styling {
public constructor(
public tooltipModel: any,
public element: HTMLElement,
public topPosition: number,
public leftPosition: number,
public chartPosition: ClientRect,
) {}
}
/**
* TooltipParams holds tooltip's configuration
*/
export class TooltipParams {
public constructor(
public tooltipModel: any,
public chartId: string,
public tooltipId: string,
public arrowId: string,
public pointId: string,
public markUp: string,
public tooltipTop: number,
public tooltipLeft: number,
public arrowTop: number,
public arrowLeft: number,
public pointTop: number,
public pointLeft: number,
public color: string,
) {}
}
/**
* Tooltip provides custom tooltip rendering
*/
export class Tooltip {
public static custom(params: TooltipParams): void {
const chart = document.getElementById(params.chartId);
if (!chart) {
return;
}
const tooltip: HTMLElement = Tooltip.createTooltip(params.tooltipId);
const arrow: HTMLElement = Tooltip.createArrow(params.arrowId);
const point: HTMLElement = Tooltip.createPoint(params.pointId);
if (!params.tooltipModel.opacity) {
Tooltip.remove(tooltip, arrow, point);
return;
}
if (params.tooltipModel.body) {
Tooltip.render(tooltip, params.markUp);
}
const position = chart.getBoundingClientRect();
const tooltipStyling = new Styling(params.tooltipModel, tooltip, params.tooltipTop, params.tooltipLeft, position);
Tooltip.elemStyling(tooltipStyling);
const arrowStyling = new Styling(params.tooltipModel, arrow, params.arrowTop, params.arrowLeft, position);
Tooltip.elemStyling(arrowStyling);
const pointStyling = new Styling(params.tooltipModel, point, params.pointTop, params.pointLeft, position);
Tooltip.elemStyling(pointStyling);
Tooltip.pointStyling(point, params.color);
}
private static createTooltip(id: string): HTMLElement {
let tooltipEl = document.getElementById(id);
if (!tooltipEl) {
tooltipEl = document.createElement('div');
tooltipEl.id = id;
document.body.appendChild(tooltipEl);
}
return tooltipEl;
}
private static createArrow(id: string): HTMLElement {
let tooltipArrow = document.getElementById(id);
if (!tooltipArrow) {
tooltipArrow = document.createElement('div');
tooltipArrow.id = id;
document.body.appendChild(tooltipArrow);
}
return tooltipArrow;
}
private static createPoint(id: string): HTMLElement {
let tooltipPoint = document.getElementById(id);
if (!tooltipPoint) {
tooltipPoint = document.createElement('div');
tooltipPoint.id = id;
document.body.appendChild(tooltipPoint);
}
return tooltipPoint;
}
private static remove(tooltipEl: HTMLElement, tooltipArrow: HTMLElement, tooltipPoint: HTMLElement) {
document.body.removeChild(tooltipEl);
document.body.removeChild(tooltipArrow);
document.body.removeChild(tooltipPoint);
}
private static render(tooltip: HTMLElement, markUp: string) {
tooltip.innerHTML = markUp;
}
private static elemStyling(elemStyling: Styling) {
elemStyling.element.style.opacity = StylingConstants.tooltipOpacity;
elemStyling.element.style.position = StylingConstants.tooltipPosition;
elemStyling.element.style.left = `${elemStyling.chartPosition.left + elemStyling.tooltipModel.caretX - elemStyling.leftPosition}px`;
elemStyling.element.style.top = `${elemStyling.chartPosition.top + window.pageYOffset + elemStyling.tooltipModel.caretY - elemStyling.topPosition}px`;
}
private static pointStyling(point: HTMLElement, color: string) {
point.style.width = StylingConstants.pointWidth;
point.style.height = StylingConstants.pointHeight;
point.style.backgroundColor = color;
point.style.borderRadius = StylingConstants.borderRadius;
}
}