web/multinode: disk space usage and stat charts
Change-Id: Ib2b1d6f2b78d57bd43ae1152921d98a1d6c31243
This commit is contained in:
parent
b900f6b4f9
commit
1230cde317
@ -25,6 +25,10 @@ export class BandwidthClient extends APIClient {
|
|||||||
public async fetch(satelliteId: string | null, nodeId: string | null): Promise<BandwidthTraffic> {
|
public async fetch(satelliteId: string | null, nodeId: string | null): Promise<BandwidthTraffic> {
|
||||||
let path = `${this.ROOT_PATH}`;
|
let path = `${this.ROOT_PATH}`;
|
||||||
|
|
||||||
|
if (!satelliteId && !nodeId) {
|
||||||
|
path += '/';
|
||||||
|
}
|
||||||
|
|
||||||
if (satelliteId) {
|
if (satelliteId) {
|
||||||
path += `/satellites/${satelliteId}`;
|
path += `/satellites/${satelliteId}`;
|
||||||
}
|
}
|
||||||
@ -40,9 +44,10 @@ export class BandwidthClient extends APIClient {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const traffic = await response.json();
|
const traffic = await response.json();
|
||||||
|
const daily = traffic.bandwidthDaily || [];
|
||||||
|
|
||||||
return new BandwidthTraffic(
|
return new BandwidthTraffic(
|
||||||
traffic.bandwidthDaily.map(daily => {
|
daily.map(daily => {
|
||||||
return new BandwidthRollup(
|
return new BandwidthRollup(
|
||||||
new Egress(daily.egress.repair, daily.egress.audit, daily.egress.usage),
|
new Egress(daily.egress.repair, daily.egress.audit, daily.egress.usage),
|
||||||
new Ingress(daily.ingress.repair, daily.ingress.usage),
|
new Ingress(daily.ingress.repair, daily.ingress.usage),
|
||||||
|
@ -33,6 +33,13 @@ export class StorageClient extends APIClient {
|
|||||||
path += `/${nodeId}`;
|
path += `/${nodeId}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const now = new Date();
|
||||||
|
const year = now.getUTCFullYear();
|
||||||
|
const month = now.getUTCMonth() + 1;
|
||||||
|
const period = `${year}-${month > 9 ? month : `0${month}`}`;
|
||||||
|
|
||||||
|
path += `?period=${period}`;
|
||||||
|
|
||||||
const response = await this.http.get(path);
|
const response = await this.http.get(path);
|
||||||
|
|
||||||
if (!response.ok) {
|
if (!response.ok) {
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
// Copyright (C) 2019 Storj Labs, Inc.
|
// Copyright (C) 2021 Storj Labs, Inc.
|
||||||
// See LICENSE for copying information.
|
// See LICENSE for copying information.
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
// Copyright (C) 2019 Storj Labs, Inc.
|
// Copyright (C) 2021 Storj Labs, Inc.
|
||||||
// See LICENSE for copying information.
|
// See LICENSE for copying information.
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
// Copyright (C) 2019 Storj Labs, Inc.
|
// Copyright (C) 2021 Storj Labs, Inc.
|
||||||
// See LICENSE for copying information.
|
// See LICENSE for copying information.
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
// Copyright (C) 2019 Storj Labs, Inc.
|
// Copyright (C) 2021 Storj Labs, Inc.
|
||||||
// See LICENSE for copying information.
|
// See LICENSE for copying information.
|
||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
|
36
web/multinode/src/app/components/common/DoughnutChart.vue
Normal file
36
web/multinode/src/app/components/common/DoughnutChart.vue
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
// Copyright (C) 2021 Storj Labs, Inc.
|
||||||
|
// See LICENSE for copying information.
|
||||||
|
|
||||||
|
<script lang="ts">
|
||||||
|
import * as VueChart from 'vue-chartjs';
|
||||||
|
import { Component, Prop, Vue, Watch } from 'vue-property-decorator';
|
||||||
|
|
||||||
|
import { DiskStatChartData } from '@/app/types/chart';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
extends: VueChart.Doughnut,
|
||||||
|
})
|
||||||
|
export default class DoughnutChart extends Vue {
|
||||||
|
@Prop({default: () => new DiskStatChartData()})
|
||||||
|
private readonly chartData: DiskStatChartData;
|
||||||
|
|
||||||
|
@Watch('chartData')
|
||||||
|
private onDataChange(news: object, old: object): void {
|
||||||
|
(this as any).renderChart(this.chartData, {
|
||||||
|
hover: false,
|
||||||
|
tooltips: {
|
||||||
|
enabled: false,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public mounted(): void {
|
||||||
|
(this as any).renderChart(this.chartData, {
|
||||||
|
hover: false,
|
||||||
|
tooltips: {
|
||||||
|
enabled: false,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
@ -4,7 +4,7 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="add-new-node">
|
<div class="add-new-node">
|
||||||
<v-button :with-plus="true" label="New Node" :on-press="openModal" width="152px" />
|
<v-button :with-plus="true" label="New Node" :on-press="openModal" width="152px" />
|
||||||
<v-modal v-if="isAddNewNodeModalShown" @close="closeModal">
|
<v-modal v-if="isAddNewNodeModalShown" @onClose="closeModal">
|
||||||
<h2 slot="header">Add New Node</h2>
|
<h2 slot="header">Add New Node</h2>
|
||||||
<div class="add-new-node__body" slot="body">
|
<div class="add-new-node__body" slot="body">
|
||||||
<headered-input
|
<headered-input
|
||||||
|
143
web/multinode/src/app/components/storage/DiskSpaceChart.vue
Normal file
143
web/multinode/src/app/components/storage/DiskSpaceChart.vue
Normal file
@ -0,0 +1,143 @@
|
|||||||
|
// Copyright (C) 2021 Storj Labs, Inc.
|
||||||
|
// See LICENSE for copying information.
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div class="chart">
|
||||||
|
<p class="disk-space-chart__data-dimension">{{ chartDataDimension }}*h</p>
|
||||||
|
<VChart
|
||||||
|
id="disk-space-chart"
|
||||||
|
:chart-data="chartData"
|
||||||
|
:width="chartWidth"
|
||||||
|
:height="chartHeight"
|
||||||
|
:tooltip-constructor="diskSpaceTooltip"
|
||||||
|
:key="chartKey"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts">
|
||||||
|
import { Component } from 'vue-property-decorator';
|
||||||
|
|
||||||
|
import BaseChart from '@/app/components/common/BaseChart.vue';
|
||||||
|
|
||||||
|
import { ChartData, Tooltip, TooltipParams } from '@/app/types/chart';
|
||||||
|
import { Chart as ChartUtils } from '@/app/utils/chart';
|
||||||
|
import { Size } from '@/private/memory/size';
|
||||||
|
import { Stamp } from '@/storage';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* stores stamp data for disc space chart's tooltip
|
||||||
|
*/
|
||||||
|
class StampTooltip {
|
||||||
|
public atRestTotal: string;
|
||||||
|
public date: string;
|
||||||
|
|
||||||
|
public constructor(stamp: Stamp) {
|
||||||
|
this.atRestTotal = Size.toBase10String(stamp.atRestTotal);
|
||||||
|
this.date = stamp.intervalStart.toUTCString().slice(0, 16);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Component
|
||||||
|
export default class DiskSpaceChart extends BaseChart {
|
||||||
|
|
||||||
|
private get allStamps(): Stamp[] {
|
||||||
|
return ChartUtils.populateEmptyStamps(this.$store.state.storage.usage);
|
||||||
|
}
|
||||||
|
|
||||||
|
public get chartDataDimension(): string {
|
||||||
|
if (!this.$store.state.storage.usage.length) {
|
||||||
|
return 'Bytes';
|
||||||
|
}
|
||||||
|
|
||||||
|
return ChartUtils.getChartDataDimension(this.allStamps.map((elem) => {
|
||||||
|
return elem.atRestTotal;
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
|
public get chartData(): ChartData {
|
||||||
|
let data: number[] = [0];
|
||||||
|
const daysCount = ChartUtils.daysDisplayedOnChart();
|
||||||
|
const chartBackgroundColor = '#4F97F7';
|
||||||
|
const chartBorderColor = '#1F49A3';
|
||||||
|
const chartBorderWidth = 1;
|
||||||
|
|
||||||
|
if (this.allStamps.length) {
|
||||||
|
data = ChartUtils.normalizeChartData(this.allStamps.map(elem => elem.atRestTotal));
|
||||||
|
}
|
||||||
|
|
||||||
|
return new ChartData(daysCount, chartBackgroundColor, chartBorderColor, chartBorderWidth, data);
|
||||||
|
}
|
||||||
|
|
||||||
|
public diskSpaceTooltip(tooltipModel): void {
|
||||||
|
const tooltipParams = new TooltipParams(tooltipModel, 'disk-space-chart', 'disk-space-tooltip', 'disk-space-tooltip-point', this.tooltipMarkUp(tooltipModel),
|
||||||
|
125, 89, 6, 4, `#1f49a3`);
|
||||||
|
|
||||||
|
Tooltip.custom(tooltipParams);
|
||||||
|
}
|
||||||
|
|
||||||
|
private tooltipMarkUp(tooltipModel: any): string {
|
||||||
|
if (!tooltipModel.dataPoints) {
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
|
||||||
|
const dataIndex = tooltipModel.dataPoints[0].index;
|
||||||
|
const dataPoint = new StampTooltip(this.allStamps[dataIndex]);
|
||||||
|
|
||||||
|
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>
|
||||||
|
|
||||||
|
<style lang="scss">
|
||||||
|
p {
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.disk-space-chart {
|
||||||
|
z-index: 102;
|
||||||
|
|
||||||
|
&__data-dimension {
|
||||||
|
font-size: 13px;
|
||||||
|
color: var(--c-title);
|
||||||
|
margin: 0 0 5px 31px !important;
|
||||||
|
font-family: 'font_medium', sans-serif;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#disk-space-tooltip {
|
||||||
|
background: white;
|
||||||
|
border: 1px solid var(--c-gray--light);
|
||||||
|
width: 180px;
|
||||||
|
height: 90px;
|
||||||
|
font-size: 12px;
|
||||||
|
border-radius: 14px;
|
||||||
|
color: var(--c-title);
|
||||||
|
pointer-events: none;
|
||||||
|
z-index: 9999;
|
||||||
|
font-family: 'font_bold', sans-serif;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tooltip-body {
|
||||||
|
|
||||||
|
&__data {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
padding: 11px 44px;
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__footer {
|
||||||
|
font-size: 12px;
|
||||||
|
width: auto;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
padding: 10px 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
275
web/multinode/src/app/components/storage/DiskStatChart.vue
Normal file
275
web/multinode/src/app/components/storage/DiskStatChart.vue
Normal file
@ -0,0 +1,275 @@
|
|||||||
|
// Copyright (C) 2021 Storj Labs, Inc.
|
||||||
|
// See LICENSE for copying information.
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div class="disk-stat-area">
|
||||||
|
<p class="disk-stat-area__title">Total Disk Space</p>
|
||||||
|
<p class="disk-stat-area__amount">{{ diskSpace.allocated | bytesToBase10String }}</p>
|
||||||
|
<doughnut-chart class="disk-stat-area__chart" :chart-data="chartData" />
|
||||||
|
<div class="disk-stat-area__info-area">
|
||||||
|
<div class="disk-stat-area__info-area__item">
|
||||||
|
<div class="disk-stat-area__info-area__item__labels-area">
|
||||||
|
<div class="disk-stat-area__info-area__item__labels-area__circle used"></div>
|
||||||
|
<p class="disk-stat-area__info-area__item__labels-area__label">Used</p>
|
||||||
|
</div>
|
||||||
|
<p class="disk-stat-area__info-area__item__labels-area__amount">{{ diskSpace.usedPieces | bytesToBase10String }}</p>
|
||||||
|
</div>
|
||||||
|
<div class="disk-stat-area__info-area__item">
|
||||||
|
<div class="disk-stat-area__info-area__item__labels-area">
|
||||||
|
<div class="disk-stat-area__info-area__item__labels-area__circle free"></div>
|
||||||
|
<p class="disk-stat-area__info-area__item__labels-area__label">Free</p>
|
||||||
|
</div>
|
||||||
|
<p class="disk-stat-area__info-area__item__labels-area__amount">{{ diskSpace.free | bytesToBase10String }}</p>
|
||||||
|
</div>
|
||||||
|
<div class="disk-stat-area__info-area__item">
|
||||||
|
<div class="disk-stat-area__info-area__item__labels-area">
|
||||||
|
<div class="disk-stat-area__info-area__item__labels-area__circle trash"></div>
|
||||||
|
<p class="disk-stat-area__info-area__item__labels-area__label">Trash</p>
|
||||||
|
</div>
|
||||||
|
<p class="disk-stat-area__info-area__item__labels-area__amount">{{ diskSpace.usedTrash | bytesToBase10String }}</p>
|
||||||
|
</div>
|
||||||
|
<div class="disk-stat-area__info-area__item">
|
||||||
|
<div class="disk-stat-area__info-area__item__labels-area">
|
||||||
|
<div class="disk-stat-area__info-area__item__labels-area__circle overused"></div>
|
||||||
|
<p class="disk-stat-area__info-area__item__labels-area__label">Overused</p>
|
||||||
|
</div>
|
||||||
|
<p class="disk-stat-area__info-area__item__labels-area__amount">{{ diskSpace.overused | bytesToBase10String }}</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts">
|
||||||
|
import { Component, Vue } from 'vue-property-decorator';
|
||||||
|
|
||||||
|
import DoughnutChart from '@/app/components/common/DoughnutChart.vue';
|
||||||
|
|
||||||
|
import { DiskStatChartData, DiskStatDataSet } from '@/app/types/chart';
|
||||||
|
import { DiskSpace } from '@/storage';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
components: { DoughnutChart },
|
||||||
|
})
|
||||||
|
export default class DiskStatChart extends Vue {
|
||||||
|
/**
|
||||||
|
* Holds datasets for chart.
|
||||||
|
*/
|
||||||
|
public get chartData(): DiskStatChartData {
|
||||||
|
return new DiskStatChartData([
|
||||||
|
new DiskStatDataSet(
|
||||||
|
'',
|
||||||
|
['#D6D6D6', '#0059D0', '#8FA7C6', '#EB5757'],
|
||||||
|
[
|
||||||
|
this.diskSpace.free,
|
||||||
|
this.diskSpace.usedPieces,
|
||||||
|
this.diskSpace.usedTrash,
|
||||||
|
this.diskSpace.overused,
|
||||||
|
],
|
||||||
|
),
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns disk space information from store.
|
||||||
|
*/
|
||||||
|
public get diskSpace(): DiskSpace {
|
||||||
|
return this.$store.state.storage.diskSpace;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss">
|
||||||
|
|
||||||
|
.disk-stat-area {
|
||||||
|
width: 400px;
|
||||||
|
height: 336px;
|
||||||
|
background-color: white;
|
||||||
|
border: 1px solid var(--c-gray--light);
|
||||||
|
border-radius: 11px;
|
||||||
|
padding: 32px 20px;
|
||||||
|
position: relative;
|
||||||
|
|
||||||
|
&__title {
|
||||||
|
font-family: 'font_regular', sans-serif;
|
||||||
|
font-size: 14px;
|
||||||
|
color: var(--c-gray);
|
||||||
|
user-select: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__amount {
|
||||||
|
font-family: 'font_bold', sans-serif;
|
||||||
|
font-size: 32px;
|
||||||
|
line-height: 57px;
|
||||||
|
color: var(--c-title);
|
||||||
|
margin-top: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__chart {
|
||||||
|
position: absolute;
|
||||||
|
width: calc(58% - 25px);
|
||||||
|
height: 220px;
|
||||||
|
top: 135px;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__info-area {
|
||||||
|
position: absolute;
|
||||||
|
right: 30px;
|
||||||
|
top: 60%;
|
||||||
|
transform: translateY(-50%);
|
||||||
|
width: calc(40% - 35px);
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
box-sizing: border-box;
|
||||||
|
|
||||||
|
&__item {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
flex-direction: column;
|
||||||
|
margin-top: 19px;
|
||||||
|
|
||||||
|
&:first-of-type {
|
||||||
|
margin-top: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__labels-area {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
|
||||||
|
&__circle {
|
||||||
|
width: 14px;
|
||||||
|
height: 14px;
|
||||||
|
border-radius: 50%;
|
||||||
|
margin-right: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__label {
|
||||||
|
font-family: 'font_regular', sans-serif;
|
||||||
|
font-size: 14px;
|
||||||
|
color: #586474;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__amount {
|
||||||
|
font-family: 'font_bold', sans-serif;
|
||||||
|
font-weight: bold;
|
||||||
|
font-size: 14px;
|
||||||
|
color: var(--c-title);
|
||||||
|
margin-left: 22px;
|
||||||
|
margin-top: 6px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.used {
|
||||||
|
background: #0059d0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.free {
|
||||||
|
background: #d6d6d6;
|
||||||
|
}
|
||||||
|
|
||||||
|
.trash {
|
||||||
|
background: #8fa7c6;
|
||||||
|
}
|
||||||
|
|
||||||
|
.overused {
|
||||||
|
background: #eb5757;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media screen and (max-width: 1000px) {
|
||||||
|
|
||||||
|
.disk-stat-area {
|
||||||
|
width: calc(100% - 60px);
|
||||||
|
|
||||||
|
&__chart {
|
||||||
|
width: 250px;
|
||||||
|
height: 250px;
|
||||||
|
margin-left: 100px;
|
||||||
|
top: 100px;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__info-area {
|
||||||
|
right: 120px;
|
||||||
|
width: 185px;
|
||||||
|
|
||||||
|
&__item {
|
||||||
|
flex-direction: row;
|
||||||
|
|
||||||
|
&__labels-area__amount {
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media screen and (max-width: 780px) {
|
||||||
|
|
||||||
|
.disk-stat-area {
|
||||||
|
|
||||||
|
&__chart {
|
||||||
|
margin-left: 50px;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__info-area {
|
||||||
|
right: 90px;
|
||||||
|
width: 140px;
|
||||||
|
|
||||||
|
&__item {
|
||||||
|
flex-direction: row;
|
||||||
|
|
||||||
|
&__labels-area__amount {
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media screen and (max-width: 640px) {
|
||||||
|
|
||||||
|
.disk-stat-area {
|
||||||
|
|
||||||
|
&__chart {
|
||||||
|
top: 125px;
|
||||||
|
width: 200px;
|
||||||
|
height: 200px;
|
||||||
|
margin-left: 50px;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__info-area {
|
||||||
|
top: 55%;
|
||||||
|
right: 90px;
|
||||||
|
width: 140px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media screen and (max-width: 550px) {
|
||||||
|
|
||||||
|
.disk-stat-area {
|
||||||
|
height: 414px;
|
||||||
|
width: calc(100% - 36px);
|
||||||
|
padding: 24px 18px;
|
||||||
|
|
||||||
|
&__chart {
|
||||||
|
top: 100px;
|
||||||
|
width: 200px;
|
||||||
|
height: 200px;
|
||||||
|
left: 50%;
|
||||||
|
transform: translateX(-50%);
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__info-area {
|
||||||
|
top: 70%;
|
||||||
|
right: 50%;
|
||||||
|
transform: translateX(50%);
|
||||||
|
bottom: 10px;
|
||||||
|
height: 100px;
|
||||||
|
width: 200px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
@ -8,7 +8,7 @@
|
|||||||
<node-selection-dropdown />
|
<node-selection-dropdown />
|
||||||
<satellite-selection-dropdown />
|
<satellite-selection-dropdown />
|
||||||
</div>
|
</div>
|
||||||
<div class="chart-container">
|
<div class="chart-container bandwidth-chart">
|
||||||
<div class="chart-container__title-area">
|
<div class="chart-container__title-area">
|
||||||
<p class="chart-container__title-area__title">Bandwidth Used This Month</p>
|
<p class="chart-container__title-area__title">Bandwidth Used This Month</p>
|
||||||
<div class="chart-container__title-area__buttons-area">
|
<div class="chart-container__title-area__buttons-area">
|
||||||
@ -42,11 +42,25 @@
|
|||||||
<p class="chart-container__amount" v-else-if="isIngressChartShown"><b>{{ bandwidth.ingressSummary | bytesToBase10String }}</b></p>
|
<p class="chart-container__amount" v-else-if="isIngressChartShown"><b>{{ bandwidth.ingressSummary | bytesToBase10String }}</b></p>
|
||||||
<p class="chart-container__amount" v-else><b>{{ bandwidth.bandwidthSummary | bytesToBase10String }}</b></p>
|
<p class="chart-container__amount" v-else><b>{{ bandwidth.bandwidthSummary | bytesToBase10String }}</b></p>
|
||||||
<div class="chart-container__chart" ref="chart" onresize="recalculateChartDimensions()" >
|
<div class="chart-container__chart" ref="chart" onresize="recalculateChartDimensions()" >
|
||||||
<EgressChart v-if="isEgressChartShown" :height="chartHeight" :width="chartWidth"/>
|
<egress-chart v-if="isEgressChartShown" :height="chartHeight" :width="chartWidth"/>
|
||||||
<IngressChart v-else-if="isIngressChartShown" :height="chartHeight" :width="chartWidth"/>
|
<ingress-chart v-else-if="isIngressChartShown" :height="chartHeight" :width="chartWidth"/>
|
||||||
<BandwidthChart v-else :height="chartHeight" :width="chartWidth"/>
|
<bandwidth-chart v-else :height="chartHeight" :width="chartWidth"/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<section class="bandwidth__chart-area">
|
||||||
|
<section class="chart-container">
|
||||||
|
<div class="chart-container__title-area disk-space-title">
|
||||||
|
<p class="chart-container__title-area__title">Disk Space Used This Month</p>
|
||||||
|
</div>
|
||||||
|
<p class="chart-container__amount disk-space-amount"><b>{{ 0 | bytesToBase10String }}*h</b></p>
|
||||||
|
<div class="chart-container__chart" ref="diskSpaceChart" onresize="recalculateChartDimensions()" >
|
||||||
|
<disk-space-chart :height="diskSpaceChartHeight" :width="diskSpaceChartWidth"/>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
<section class="disk-stat-chart">
|
||||||
|
<disk-stat-chart />
|
||||||
|
</section>
|
||||||
|
</section>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
@ -58,12 +72,16 @@ import EgressChart from '@/app/components/bandwidth/EgressChart.vue';
|
|||||||
import IngressChart from '@/app/components/bandwidth/IngressChart.vue';
|
import IngressChart from '@/app/components/bandwidth/IngressChart.vue';
|
||||||
import NodeSelectionDropdown from '@/app/components/common/NodeSelectionDropdown.vue';
|
import NodeSelectionDropdown from '@/app/components/common/NodeSelectionDropdown.vue';
|
||||||
import SatelliteSelectionDropdown from '@/app/components/common/SatelliteSelectionDropdown.vue';
|
import SatelliteSelectionDropdown from '@/app/components/common/SatelliteSelectionDropdown.vue';
|
||||||
|
import DiskSpaceChart from '@/app/components/storage/DiskSpaceChart.vue';
|
||||||
|
import DiskStatChart from '@/app/components/storage/DiskStatChart.vue';
|
||||||
|
|
||||||
import { UnauthorizedError } from '@/api';
|
import { UnauthorizedError } from '@/api';
|
||||||
import { BandwidthTraffic } from '@/bandwidth';
|
import { BandwidthTraffic } from '@/bandwidth';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
components: {
|
components: {
|
||||||
|
DiskStatChart,
|
||||||
|
DiskSpaceChart,
|
||||||
EgressChart,
|
EgressChart,
|
||||||
IngressChart,
|
IngressChart,
|
||||||
BandwidthChart,
|
BandwidthChart,
|
||||||
@ -74,6 +92,8 @@ import { BandwidthTraffic } from '@/bandwidth';
|
|||||||
export default class BandwidthPage extends Vue {
|
export default class BandwidthPage extends Vue {
|
||||||
public chartWidth: number = 0;
|
public chartWidth: number = 0;
|
||||||
public chartHeight: number = 0;
|
public chartHeight: number = 0;
|
||||||
|
public diskSpaceChartWidth: number = 0;
|
||||||
|
public diskSpaceChartHeight: number = 0;
|
||||||
public isEgressChartShown: boolean = false;
|
public isEgressChartShown: boolean = false;
|
||||||
public isIngressChartShown: boolean = false;
|
public isIngressChartShown: boolean = false;
|
||||||
public $refs: {
|
public $refs: {
|
||||||
@ -90,6 +110,8 @@ export default class BandwidthPage extends Vue {
|
|||||||
public recalculateChartDimensions(): void {
|
public recalculateChartDimensions(): void {
|
||||||
this.chartWidth = this.$refs['chart'].clientWidth;
|
this.chartWidth = this.$refs['chart'].clientWidth;
|
||||||
this.chartHeight = this.$refs['chart'].clientHeight;
|
this.chartHeight = this.$refs['chart'].clientHeight;
|
||||||
|
this.diskSpaceChartWidth = this.$refs['diskSpaceChart'].clientWidth;
|
||||||
|
this.diskSpaceChartHeight = this.$refs['diskSpaceChart'].clientHeight;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -109,14 +131,14 @@ export default class BandwidthPage extends Vue {
|
|||||||
// TODO: notify error
|
// TODO: notify error
|
||||||
}
|
}
|
||||||
|
|
||||||
await this.fetchBandwidth();
|
await this.fetchTraffic();
|
||||||
|
|
||||||
// Subscribes on period or satellite change
|
// Subscribes on period or satellite change
|
||||||
this.$store.subscribe(async (mutation) => {
|
this.$store.subscribe(async (mutation) => {
|
||||||
const watchedMutations = [ 'nodes/setSelectedNode', 'nodes/setSelectedSatellite' ];
|
const watchedMutations = [ 'nodes/setSelectedNode', 'nodes/setSelectedSatellite' ];
|
||||||
|
|
||||||
if (watchedMutations.includes(mutation.type)) {
|
if (watchedMutations.includes(mutation.type)) {
|
||||||
await this.fetchBandwidth();
|
await this.fetchTraffic();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -156,9 +178,9 @@ export default class BandwidthPage extends Vue {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Fetches bandwidth information.
|
* Fetches bandwidth and disk space information.
|
||||||
*/
|
*/
|
||||||
private async fetchBandwidth(): Promise<void> {
|
private async fetchTraffic(): Promise<void> {
|
||||||
try {
|
try {
|
||||||
await this.$store.dispatch('bandwidth/fetch');
|
await this.$store.dispatch('bandwidth/fetch');
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
@ -168,6 +190,26 @@ export default class BandwidthPage extends Vue {
|
|||||||
|
|
||||||
// TODO: notify error
|
// TODO: notify error
|
||||||
}
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
await this.$store.dispatch('storage/usage');
|
||||||
|
} catch (error) {
|
||||||
|
if (error instanceof UnauthorizedError) {
|
||||||
|
// TODO: redirect to login screen.
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: notify error
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
await this.$store.dispatch('storage/diskSpace');
|
||||||
|
} catch (error) {
|
||||||
|
if (error instanceof UnauthorizedError) {
|
||||||
|
// TODO: redirect to login screen.
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: notify error
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
@ -203,7 +245,7 @@ export default class BandwidthPage extends Vue {
|
|||||||
|
|
||||||
& .chart-container {
|
& .chart-container {
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
width: 100%;
|
width: 65%;
|
||||||
height: 401px;
|
height: 401px;
|
||||||
background-color: white;
|
background-color: white;
|
||||||
border: 1px solid var(--c-gray--light);
|
border: 1px solid var(--c-gray--light);
|
||||||
@ -263,5 +305,25 @@ export default class BandwidthPage extends Vue {
|
|||||||
height: 240px;
|
height: 240px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&__chart-area {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
justify-content: space-between;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.disk-space-amount {
|
||||||
|
margin-top: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bandwidth-chart {
|
||||||
|
width: 100% !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.disk-stat-chart {
|
||||||
|
margin: 20px 0 13px 0;
|
||||||
|
width: auto;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
@ -7,7 +7,7 @@ exports[`BandwidthPage renders correctly 1`] = `
|
|||||||
<node-selection-dropdown-stub></node-selection-dropdown-stub>
|
<node-selection-dropdown-stub></node-selection-dropdown-stub>
|
||||||
<satellite-selection-dropdown-stub></satellite-selection-dropdown-stub>
|
<satellite-selection-dropdown-stub></satellite-selection-dropdown-stub>
|
||||||
</div>
|
</div>
|
||||||
<div class="chart-container">
|
<div class="chart-container bandwidth-chart">
|
||||||
<div class="chart-container__title-area">
|
<div class="chart-container__title-area">
|
||||||
<p class="chart-container__title-area__title">Bandwidth Used This Month</p>
|
<p class="chart-container__title-area__title">Bandwidth Used This Month</p>
|
||||||
<div class="chart-container__title-area__buttons-area"><button name="Show Bandwidth Chart" class="chart-container__title-area__chart-choice-item active">
|
<div class="chart-container__title-area__buttons-area"><button name="Show Bandwidth Chart" class="chart-container__title-area__chart-choice-item active">
|
||||||
@ -20,9 +20,23 @@ exports[`BandwidthPage renders correctly 1`] = `
|
|||||||
</div>
|
</div>
|
||||||
<p class="chart-container__amount"><b>0.7GB</b></p>
|
<p class="chart-container__amount"><b>0.7GB</b></p>
|
||||||
<div onresize="recalculateChartDimensions()" class="chart-container__chart">
|
<div onresize="recalculateChartDimensions()" class="chart-container__chart">
|
||||||
<bandwidthchart-stub width="0" height="0"></bandwidthchart-stub>
|
<bandwidth-chart-stub width="0" height="0"></bandwidth-chart-stub>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<section class="bandwidth__chart-area">
|
||||||
|
<section class="chart-container">
|
||||||
|
<div class="chart-container__title-area disk-space-title">
|
||||||
|
<p class="chart-container__title-area__title">Disk Space Used This Month</p>
|
||||||
|
</div>
|
||||||
|
<p class="chart-container__amount disk-space-amount"><b>0B*h</b></p>
|
||||||
|
<div onresize="recalculateChartDimensions()" class="chart-container__chart">
|
||||||
|
<disk-space-chart-stub width="0" height="0"></disk-space-chart-stub>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
<section class="disk-stat-chart">
|
||||||
|
<disk-stat-chart-stub></disk-stat-chart-stub>
|
||||||
|
</section>
|
||||||
|
</section>
|
||||||
</div>
|
</div>
|
||||||
`;
|
`;
|
||||||
|
|
||||||
@ -33,7 +47,7 @@ exports[`BandwidthPage renders correctly with egress chart 1`] = `
|
|||||||
<node-selection-dropdown-stub></node-selection-dropdown-stub>
|
<node-selection-dropdown-stub></node-selection-dropdown-stub>
|
||||||
<satellite-selection-dropdown-stub></satellite-selection-dropdown-stub>
|
<satellite-selection-dropdown-stub></satellite-selection-dropdown-stub>
|
||||||
</div>
|
</div>
|
||||||
<div class="chart-container">
|
<div class="chart-container bandwidth-chart">
|
||||||
<div class="chart-container__title-area">
|
<div class="chart-container__title-area">
|
||||||
<p class="chart-container__title-area__title">Bandwidth Used This Month</p>
|
<p class="chart-container__title-area__title">Bandwidth Used This Month</p>
|
||||||
<div class="chart-container__title-area__buttons-area"><button name="Show Bandwidth Chart" class="chart-container__title-area__chart-choice-item">
|
<div class="chart-container__title-area__buttons-area"><button name="Show Bandwidth Chart" class="chart-container__title-area__chart-choice-item">
|
||||||
@ -46,9 +60,23 @@ exports[`BandwidthPage renders correctly with egress chart 1`] = `
|
|||||||
</div>
|
</div>
|
||||||
<p class="chart-container__amount"><b>577.7GB</b></p>
|
<p class="chart-container__amount"><b>577.7GB</b></p>
|
||||||
<div onresize="recalculateChartDimensions()" class="chart-container__chart">
|
<div onresize="recalculateChartDimensions()" class="chart-container__chart">
|
||||||
<egresschart-stub width="0" height="0"></egresschart-stub>
|
<egress-chart-stub width="0" height="0"></egress-chart-stub>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<section class="bandwidth__chart-area">
|
||||||
|
<section class="chart-container">
|
||||||
|
<div class="chart-container__title-area disk-space-title">
|
||||||
|
<p class="chart-container__title-area__title">Disk Space Used This Month</p>
|
||||||
|
</div>
|
||||||
|
<p class="chart-container__amount disk-space-amount"><b>0B*h</b></p>
|
||||||
|
<div onresize="recalculateChartDimensions()" class="chart-container__chart">
|
||||||
|
<disk-space-chart-stub width="0" height="0"></disk-space-chart-stub>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
<section class="disk-stat-chart">
|
||||||
|
<disk-stat-chart-stub></disk-stat-chart-stub>
|
||||||
|
</section>
|
||||||
|
</section>
|
||||||
</div>
|
</div>
|
||||||
`;
|
`;
|
||||||
|
|
||||||
@ -59,7 +87,7 @@ exports[`BandwidthPage renders correctly with ingress chart 1`] = `
|
|||||||
<node-selection-dropdown-stub></node-selection-dropdown-stub>
|
<node-selection-dropdown-stub></node-selection-dropdown-stub>
|
||||||
<satellite-selection-dropdown-stub></satellite-selection-dropdown-stub>
|
<satellite-selection-dropdown-stub></satellite-selection-dropdown-stub>
|
||||||
</div>
|
</div>
|
||||||
<div class="chart-container">
|
<div class="chart-container bandwidth-chart">
|
||||||
<div class="chart-container__title-area">
|
<div class="chart-container__title-area">
|
||||||
<p class="chart-container__title-area__title">Bandwidth Used This Month</p>
|
<p class="chart-container__title-area__title">Bandwidth Used This Month</p>
|
||||||
<div class="chart-container__title-area__buttons-area"><button name="Show Bandwidth Chart" class="chart-container__title-area__chart-choice-item">
|
<div class="chart-container__title-area__buttons-area"><button name="Show Bandwidth Chart" class="chart-container__title-area__chart-choice-item">
|
||||||
@ -72,8 +100,22 @@ exports[`BandwidthPage renders correctly with ingress chart 1`] = `
|
|||||||
</div>
|
</div>
|
||||||
<p class="chart-container__amount"><b>5MB</b></p>
|
<p class="chart-container__amount"><b>5MB</b></p>
|
||||||
<div onresize="recalculateChartDimensions()" class="chart-container__chart">
|
<div onresize="recalculateChartDimensions()" class="chart-container__chart">
|
||||||
<ingresschart-stub width="0" height="0"></ingresschart-stub>
|
<ingress-chart-stub width="0" height="0"></ingress-chart-stub>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<section class="bandwidth__chart-area">
|
||||||
|
<section class="chart-container">
|
||||||
|
<div class="chart-container__title-area disk-space-title">
|
||||||
|
<p class="chart-container__title-area__title">Disk Space Used This Month</p>
|
||||||
|
</div>
|
||||||
|
<p class="chart-container__amount disk-space-amount"><b>0B*h</b></p>
|
||||||
|
<div onresize="recalculateChartDimensions()" class="chart-container__chart">
|
||||||
|
<disk-space-chart-stub width="0" height="0"></disk-space-chart-stub>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
<section class="disk-stat-chart">
|
||||||
|
<disk-stat-chart-stub></disk-stat-chart-stub>
|
||||||
|
</section>
|
||||||
|
</section>
|
||||||
</div>
|
</div>
|
||||||
`;
|
`;
|
||||||
|
Loading…
Reference in New Issue
Block a user