mirror of
https://github.com/lucaspalomodevelop/core.git
synced 2026-03-20 03:16:12 +00:00
dashboard: refactor gauges into base class, add mbuf gauge as well
This commit is contained in:
parent
f643d964c3
commit
ff3bb2f731
@ -107,9 +107,14 @@ class DashboardController extends ApiControllerBase
|
||||
],
|
||||
'firewallstates' => [
|
||||
'title' => gettext('Firewall States'),
|
||||
'current' => gettext('Current'),
|
||||
'limit' => gettext('Limit'),
|
||||
]
|
||||
'used' => gettext('Used'),
|
||||
'free' => gettext('Free'),
|
||||
],
|
||||
'mbuf' => [
|
||||
'title' => gettext('MBUF Usage'),
|
||||
'used' => gettext('Used'),
|
||||
'free' => gettext('Free'),
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
|
||||
@ -322,4 +322,9 @@ class SystemController extends ApiControllerBase
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
public function systemMbufAction()
|
||||
{
|
||||
return json_decode((new Backend())->configdRun('system show mbuf'), true);
|
||||
}
|
||||
}
|
||||
|
||||
@ -44,7 +44,7 @@
|
||||
$( document ).ready(function() {
|
||||
let widgetManager = new WidgetManager({
|
||||
float: false,
|
||||
column: 5,
|
||||
column: 6,
|
||||
margin: 10,
|
||||
alwaysShowResizeHandle: false,
|
||||
sizeToContent: true,
|
||||
|
||||
@ -126,3 +126,9 @@ command:/usr/local/bin/openssl version | cut -f -2 -d ' '
|
||||
parameters:
|
||||
type:script_output
|
||||
message:Show OpenSSL version
|
||||
|
||||
[show.mbuf]
|
||||
command:/usr/bin/netstat -m --libxo json
|
||||
parameters:
|
||||
type:script_output
|
||||
message:Show mbuf stats
|
||||
|
||||
150
src/opnsense/www/js/widgets/BaseGaugeWidget.js
Normal file
150
src/opnsense/www/js/widgets/BaseGaugeWidget.js
Normal file
@ -0,0 +1,150 @@
|
||||
/*
|
||||
* Copyright (C) 2024 Deciso B.V.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
|
||||
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
|
||||
* AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
|
||||
* OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
import BaseWidget from "./BaseWidget.js";
|
||||
|
||||
export default class BaseGaugeWidget extends BaseWidget {
|
||||
constructor() {
|
||||
super();
|
||||
|
||||
this.chart = null;
|
||||
}
|
||||
|
||||
getMarkup() {
|
||||
return $(`
|
||||
<div class="${this.id}-chart-container">
|
||||
<div class="canvas-container">
|
||||
<canvas id="${this.id}-chart"></canvas>
|
||||
</div>
|
||||
</div>
|
||||
`);
|
||||
}
|
||||
|
||||
createGaugeChart(options) {
|
||||
let _options = {
|
||||
colorMap: ['#D94F00', '#E5E5E5'],
|
||||
labels: [],
|
||||
tooltipLabelCallback: (tooltipItem) => {
|
||||
return `${tooltipItem.label}: ${tooltipItem.parsed}`;
|
||||
},
|
||||
primaryText: (data) => {
|
||||
return `${(data[0] / (data[0] + data[1]) * 100).toFixed(2)}%`;
|
||||
},
|
||||
secondaryText: (data) => false,
|
||||
...options
|
||||
}
|
||||
|
||||
|
||||
let context = document.getElementById(`${this.id}-chart`).getContext("2d");
|
||||
let config = {
|
||||
type: 'doughnut',
|
||||
data: {
|
||||
labels: _options.labels,
|
||||
datasets: [
|
||||
{
|
||||
data: [],
|
||||
backgroundColor: _options.colorMap,
|
||||
hoverBackgroundColor: _options.colorMap.map((color) => this._setAlpha(color, 0.5)),
|
||||
hoverOffset: 10,
|
||||
fill: true
|
||||
}
|
||||
]
|
||||
},
|
||||
options: {
|
||||
responsive: true,
|
||||
maintainAspectRatio: true,
|
||||
aspectRatio: 2,
|
||||
layout: {
|
||||
padding: 10
|
||||
},
|
||||
cutout: '64%',
|
||||
rotation: 270,
|
||||
circumference: 180,
|
||||
plugins: {
|
||||
legend: {
|
||||
display: false
|
||||
},
|
||||
tooltip: {
|
||||
callbacks: {
|
||||
label: _options.tooltipLabelCallback
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
plugins: [{
|
||||
id: 'custom_positioned_text',
|
||||
beforeDatasetsDraw: (chart, _, __) => {
|
||||
let data = chart.config.data.datasets[0].data;
|
||||
if (data.length !== 0) {
|
||||
let width = chart.width;
|
||||
let height = chart.height;
|
||||
let ctx = chart.ctx;
|
||||
ctx.restore();
|
||||
|
||||
let divisor = 114;
|
||||
let primaryText = _options.primaryText(data, chart);
|
||||
let secondaryText = _options.secondaryText(data, chart);
|
||||
|
||||
if (secondaryText) {
|
||||
divisor = 135;
|
||||
}
|
||||
|
||||
let fontSize = (height / divisor).toFixed(2);
|
||||
ctx.font = fontSize + "em SourceSansProSemiBold";
|
||||
ctx.textBaseline = "middle";
|
||||
|
||||
let textX = Math.round((width - ctx.measureText(primaryText).width) / 2);
|
||||
let textY = (height * 0.66);
|
||||
ctx.fillText(primaryText, textX, textY);
|
||||
|
||||
if (secondaryText) {
|
||||
let textBX = Math.round((width - ctx.measureText(secondaryText).width) / 2);
|
||||
let textBY = height * 0.83;
|
||||
ctx.fillText(secondaryText, textBX, textBY);
|
||||
}
|
||||
|
||||
ctx.save();
|
||||
}
|
||||
}
|
||||
}]
|
||||
}
|
||||
|
||||
this.chart = new Chart(context, config);
|
||||
}
|
||||
|
||||
updateChart(data) {
|
||||
if (this.chart) {
|
||||
this.chart.data.datasets[0].data = data;
|
||||
this.chart.update();
|
||||
}
|
||||
}
|
||||
|
||||
onWidgetClose() {
|
||||
if (this.chart) {
|
||||
this.chart.destroy();
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -26,13 +26,12 @@
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
import BaseWidget from "./BaseWidget.js";
|
||||
import BaseGaugeWidget from "./BaseGaugeWidget.js";
|
||||
|
||||
export default class Disk extends BaseWidget {
|
||||
export default class Disk extends BaseGaugeWidget {
|
||||
constructor() {
|
||||
super();
|
||||
|
||||
this.simple_chart = null;
|
||||
this.detailed_chart = null;
|
||||
}
|
||||
|
||||
@ -63,12 +62,12 @@ export default class Disk extends BaseWidget {
|
||||
|
||||
getMarkup() {
|
||||
return $(`
|
||||
<div class="disk-chart-container">
|
||||
<div class="${this.id}-chart-container">
|
||||
<div class="canvas-container">
|
||||
<canvas id="disk-chart"></canvas>
|
||||
<canvas id="${this.id}-chart"></canvas>
|
||||
</div>
|
||||
<div class="canvas-container">
|
||||
<canvas id="disk-detailed-chart"></canvas>
|
||||
<canvas id="${this.id}-detailed-chart"></canvas>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -76,69 +75,18 @@ export default class Disk extends BaseWidget {
|
||||
}
|
||||
|
||||
async onMarkupRendered() {
|
||||
let context_simple = document.getElementById("disk-chart").getContext("2d");
|
||||
let colorMap = ['#D94F00', '#E5E5E5'];
|
||||
let config_simple = {
|
||||
type: 'doughnut',
|
||||
data: {
|
||||
labels: [this.translations.used, this.translations.free],
|
||||
datasets: [
|
||||
{
|
||||
data: [],
|
||||
backgroundColor: colorMap,
|
||||
hoverBackgroundColor: colorMap.map((color) => this._setAlpha(color, 0.5)),
|
||||
hoveroffset: 50,
|
||||
fill: true
|
||||
},
|
||||
]
|
||||
super.createGaugeChart({
|
||||
colorMap: ['#D94F00', '#E5E5E5'],
|
||||
labels: [this.translations.used, this.translations.free],
|
||||
tooltipLabelCallback: (tooltipItem) => {
|
||||
let pct = tooltipItem.dataset.pct[tooltipItem.dataIndex];
|
||||
return `${tooltipItem.label}: ${pct}%`;
|
||||
},
|
||||
options: {
|
||||
responsive: true,
|
||||
maintainAspectRatio: true,
|
||||
aspectRatio: 2,
|
||||
layout: {
|
||||
padding: 10
|
||||
},
|
||||
cutout: '64%',
|
||||
rotation: 270,
|
||||
circumference: 180,
|
||||
plugins: {
|
||||
legend: {
|
||||
display: false
|
||||
},
|
||||
tooltip: {
|
||||
callbacks: {
|
||||
label: (tooltipItem) => {
|
||||
let pct = tooltipItem.dataset.pct[tooltipItem.dataIndex];
|
||||
return `${tooltipItem.label}: ${pct}%`;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
primaryText: (data, chart) => {
|
||||
return chart.config.data.datasets[0].pct[0] + '%';
|
||||
},
|
||||
plugins: [{
|
||||
id: 'custom_positioned_text',
|
||||
beforeDatasetsDraw: (chart, args, options) => {
|
||||
// custom plugin: draw text at 2/3 y position of chart
|
||||
if (chart.config.data.datasets[0].data.length !== 0) {
|
||||
let width = chart.width;
|
||||
let height = chart.height;
|
||||
let ctx = chart.ctx;
|
||||
ctx.restore();
|
||||
let fontSize = (height / 114).toFixed(2);
|
||||
ctx.font = fontSize + "em SourceSansProSemibold";
|
||||
ctx.textBaseline = "middle";
|
||||
let text = this.simple_chart.config.data.datasets[0].pct[0] + '%';
|
||||
let textX = Math.round((width - ctx.measureText(text).width) / 2);
|
||||
let textY = (height / 3) * 2;
|
||||
ctx.fillText(text, textX, textY);
|
||||
ctx.save();
|
||||
}
|
||||
}
|
||||
}]
|
||||
}
|
||||
})
|
||||
|
||||
this.simple_chart = new Chart(context_simple, config_simple);
|
||||
let context_detailed = document.getElementById("disk-detailed-chart").getContext("2d");
|
||||
let config = {
|
||||
type: 'bar',
|
||||
@ -218,9 +166,8 @@ export default class Disk extends BaseWidget {
|
||||
let total = this._convertToBytes(device.blocks);
|
||||
let free = total - used;
|
||||
if (device.mountpoint === '/') {
|
||||
this.simple_chart.config.data.datasets[0].data = [used, free];
|
||||
this.simple_chart.config.data.datasets[0].pct = [device.used_pct, (100 - device.used_pct)];
|
||||
this.simple_chart.update();
|
||||
this.chart.config.data.datasets[0].pct = [device.used_pct, (100 - device.used_pct)];
|
||||
super.updateChart([used, free]);
|
||||
}
|
||||
totals.push(total);
|
||||
|
||||
|
||||
@ -26,113 +26,27 @@
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
import BaseWidget from "./BaseWidget.js";
|
||||
import BaseGaugeWidget from "./BaseGaugeWidget.js";
|
||||
|
||||
export default class FirewallStates extends BaseWidget {
|
||||
export default class FirewallStates extends BaseGaugeWidget {
|
||||
constructor() {
|
||||
super();
|
||||
|
||||
this.chart = null;
|
||||
this.current = null;
|
||||
this.limit = null;
|
||||
}
|
||||
|
||||
getMarkup() {
|
||||
return $(`
|
||||
<div class="fw-states-chart-container">
|
||||
<div class="canvas-container">
|
||||
<canvas id="fw-states-chart"></canvas>
|
||||
</div>
|
||||
</div>
|
||||
`);
|
||||
}
|
||||
|
||||
async onMarkupRendered() {
|
||||
let context = document.getElementById("fw-states-chart").getContext("2d");
|
||||
let colorMap = ['#D94F00', '#E5E5E5'];
|
||||
let config = {
|
||||
type: 'doughnut',
|
||||
data: {
|
||||
labels: [this.translations.current, this.translations.limit],
|
||||
datasets: [
|
||||
{
|
||||
data: [],
|
||||
backgroundColor: colorMap,
|
||||
hoverBackgroundColor: colorMap.map((color) => this._setAlpha(color, 0.5)),
|
||||
fill: true
|
||||
}
|
||||
]
|
||||
},
|
||||
options: {
|
||||
responsive: true,
|
||||
maintainAspectRatio: true,
|
||||
aspectRatio: 2,
|
||||
layout: {
|
||||
padding: 10
|
||||
},
|
||||
cutout: '64%',
|
||||
rotation: 270,
|
||||
circumference: 180,
|
||||
plugins: {
|
||||
legend: {
|
||||
display: false
|
||||
},
|
||||
tooltip: {
|
||||
callbacks: {
|
||||
label: (tooltipItem) => {
|
||||
return `${tooltipItem.label}: ${tooltipItem.parsed}`;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
plugins: [{
|
||||
id: 'custom_positioned_text',
|
||||
beforeDatasetsDraw: (chart, args, options) => {
|
||||
if (chart.config.data.datasets[0].data.length !== 0) {
|
||||
let width = chart.width;
|
||||
let height = chart.height;
|
||||
let ctx = chart.ctx;
|
||||
ctx.restore();
|
||||
|
||||
let percentage = (this.current / this.limit * 100).toFixed(2);
|
||||
|
||||
let fontSize = (height / (percentage < 1 ? 135 : 114)).toFixed(2);
|
||||
ctx.font = fontSize + "em SourceSansProSemiBold";
|
||||
ctx.textBaseline = "middle";
|
||||
|
||||
let text = `${percentage} % `;
|
||||
let textX = Math.round((width - ctx.measureText(text).width) / 2);
|
||||
let textY = (height * 0.66);
|
||||
ctx.fillText(text, textX, textY);
|
||||
|
||||
if (percentage < 1) {
|
||||
let textB = `(${this.current} / ${this.limit})`;
|
||||
let textBX = Math.round((width - ctx.measureText(textB).width) / 2);
|
||||
let textBY = height * 0.85;
|
||||
ctx.fillText(textB, textBX, textBY);
|
||||
}
|
||||
ctx.save();
|
||||
}
|
||||
}
|
||||
}]
|
||||
}
|
||||
|
||||
this.chart = new Chart(context, config);
|
||||
super.createGaugeChart({
|
||||
labels: [this.translations.used, this.translations.free],
|
||||
secondaryText: (data) => {
|
||||
return `(${data[0]} / ${data[0] + data[1]})`;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
async onWidgetTick() {
|
||||
ajaxGet('/api/diagnostics/firewall/pf_states', {}, (data, status) => {
|
||||
this.current = parseInt(data.current);
|
||||
this.limit = parseInt(data.limit);
|
||||
this.chart.config.data.datasets[0].data = [this.current, (this.limit - this.current)];
|
||||
this.chart.update();
|
||||
let current = parseInt(data.current);
|
||||
let limit = parseInt(data.limit);
|
||||
super.updateChart([current, (limit - current)]);
|
||||
});
|
||||
}
|
||||
|
||||
onWidgetClose() {
|
||||
if (this.chart !== null) {
|
||||
this.chart.destroy();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
53
src/opnsense/www/js/widgets/Mbuf.js
Normal file
53
src/opnsense/www/js/widgets/Mbuf.js
Normal file
@ -0,0 +1,53 @@
|
||||
// endpoint:/api/core/system/system_mbuf
|
||||
|
||||
/*
|
||||
* Copyright (C) 2024 Deciso B.V.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
|
||||
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
|
||||
* AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
|
||||
* OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
import BaseGaugeWidget from "./BaseGaugeWidget.js";
|
||||
|
||||
export default class Mbuf extends BaseGaugeWidget {
|
||||
constructor() {
|
||||
super();
|
||||
}
|
||||
|
||||
async onMarkupRendered() {
|
||||
super.createGaugeChart({
|
||||
labels: [this.translations.used, this.translations.free],
|
||||
secondaryText: (data) => {
|
||||
return `(${data[0]} / ${data[0] + data[1]})`;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
async onWidgetTick() {
|
||||
ajaxGet('/api/core/system/system_mbuf', {}, (data, status) => {
|
||||
let current = parseInt(data['mbuf-statistics']['cluster-total']);
|
||||
let limit = parseInt(data['mbuf-statistics']['cluster-max']);
|
||||
super.updateChart([current, (limit - current)]);
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
@ -26,92 +26,29 @@
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
import BaseWidget from "./BaseWidget.js";
|
||||
import BaseGaugeWidget from "./BaseGaugeWidget.js";
|
||||
|
||||
export default class Memory extends BaseWidget {
|
||||
export default class Memory extends BaseGaugeWidget {
|
||||
constructor() {
|
||||
super();
|
||||
this.tickTimeout = 15000;
|
||||
|
||||
this.chart = null;
|
||||
this.curMemUsed = null;
|
||||
this.curMemTotal = null;
|
||||
}
|
||||
|
||||
getMarkup() {
|
||||
return $(`
|
||||
<div class="memory-chart-container">
|
||||
<div class="canvas-container">
|
||||
<canvas id="memory-chart"></canvas>
|
||||
</div>
|
||||
</div>
|
||||
`);
|
||||
}
|
||||
|
||||
async onMarkupRendered() {
|
||||
let context = document.getElementById("memory-chart").getContext("2d");
|
||||
let colorMap = ['#D94F00', '#A8C49B', '#E5E5E5'];
|
||||
|
||||
let config = {
|
||||
type: 'doughnut',
|
||||
data: {
|
||||
labels: [this.translations.used, this.translations.arc, this.translations.free],
|
||||
datasets: [
|
||||
{
|
||||
data: [],
|
||||
backgroundColor: colorMap,
|
||||
hoverBackgroundColor: colorMap.map((color) => this._setAlpha(color, 0.5)),
|
||||
hoveroffset: 50,
|
||||
fill: true
|
||||
},
|
||||
]
|
||||
super.createGaugeChart({
|
||||
colorMap: colorMap,
|
||||
labels: [this.translations.used, this.translations.arc, this.translations.free],
|
||||
tooltipLabelCallback: (tooltipItem) => {
|
||||
return `${tooltipItem.label}: ${tooltipItem.parsed} MB`;
|
||||
},
|
||||
options: {
|
||||
responsive: true,
|
||||
maintainAspectRatio: true,
|
||||
aspectRatio: 2,
|
||||
layout: {
|
||||
padding: 10
|
||||
},
|
||||
cutout: '64%',
|
||||
rotation: 270,
|
||||
circumference: 180,
|
||||
plugins: {
|
||||
legend: {
|
||||
display: false
|
||||
},
|
||||
tooltip: {
|
||||
callbacks: {
|
||||
label: (tooltipItem) => {
|
||||
return `${tooltipItem.label}: ${tooltipItem.parsed} MB`;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
primaryText: (data) => {
|
||||
return `${(data[0] / (data[0] + data[1] + data[2]) * 100).toFixed(2)}%`;
|
||||
},
|
||||
plugins: [{
|
||||
id: 'custom_positioned_text',
|
||||
beforeDatasetsDraw: (chart, args, options) => {
|
||||
// custom plugin: draw text at 2/3 y position of chart
|
||||
if (chart.config.data.datasets[0].data.length !== 0) {
|
||||
let width = chart.width;
|
||||
let height = chart.height;
|
||||
let ctx = chart.ctx;
|
||||
ctx.restore();
|
||||
let fontSize = (height / 114).toFixed(2);
|
||||
ctx.font = fontSize + "em SourceSansProSemibold";
|
||||
ctx.textBaseline = "middle";
|
||||
let text = (this.curMemUsed / this.curMemTotal * 100).toFixed(2) + "%";
|
||||
let textX = Math.round((width - ctx.measureText(text).width) / 2);
|
||||
let textY = (height / 3) * 2;
|
||||
ctx.fillText(text, textX, textY);
|
||||
ctx.save();
|
||||
}
|
||||
}
|
||||
}]
|
||||
}
|
||||
|
||||
this.chart = new Chart(context, config);
|
||||
secondaryText: (data) => {
|
||||
return `${data[0]} / ${data[0] + data[1] + data[2]} MB`;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
async onWidgetTick() {
|
||||
@ -120,19 +57,8 @@ export default class Memory extends BaseWidget {
|
||||
let used = parseInt(data.memory.used_frmt);
|
||||
let arc = data.memory.hasOwnProperty('arc') ? parseInt(data.memory.arc_frmt) : 0;
|
||||
let total = parseInt(data.memory.total_frmt);
|
||||
let result = [(used - arc), arc, total - used];
|
||||
this.chart.config.data.datasets[0].data = result
|
||||
|
||||
this.curMemUsed = used - arc;
|
||||
this.curMemTotal = total;
|
||||
this.chart.update();
|
||||
super.updateChart([(used - arc), arc, total - used]);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
onWidgetClose() {
|
||||
if (this.chart !== null) {
|
||||
this.chart.destroy();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user