mirror of
https://github.com/pgadmin-org/pgadmin4.git
synced 2025-02-25 18:55:31 -06:00
Use uplot for Dashboard graphs to reduce CPU usage. #5794
This commit is contained in:
@@ -17,3 +17,6 @@
|
||||
@import 'node_modules/react-checkbox-tree/lib/react-checkbox-tree.css';
|
||||
|
||||
@import 'node_modules/@simonwep/pickr/dist/themes/monolith.min.css';
|
||||
|
||||
@import 'node_modules/uplot/dist/uPlot.min.css';
|
||||
|
||||
|
||||
@@ -21,6 +21,7 @@ import getDarkTheme from './dark';
|
||||
import getHightContrastTheme from './high_contrast';
|
||||
import { CssBaseline } from '@material-ui/core';
|
||||
import pickrOverride from './overrides/pickr.override';
|
||||
import uplotOverride from './overrides/uplot.override';
|
||||
|
||||
/* Common settings across all themes */
|
||||
let basicSettings = createMuiTheme();
|
||||
@@ -313,6 +314,7 @@ function getFinalTheme(baseTheme) {
|
||||
padding: 0,
|
||||
},
|
||||
...pickrOverride(baseTheme),
|
||||
...uplotOverride(baseTheme),
|
||||
},
|
||||
},
|
||||
MuiOutlinedInput: {
|
||||
|
||||
32
web/pgadmin/static/js/Theme/overrides/uplot.override.js
Normal file
32
web/pgadmin/static/js/Theme/overrides/uplot.override.js
Normal file
@@ -0,0 +1,32 @@
|
||||
/////////////////////////////////////////////////////////////
|
||||
//
|
||||
// pgAdmin 4 - PostgreSQL Tools
|
||||
//
|
||||
// Copyright (C) 2013 - 2023, The pgAdmin Development Team
|
||||
// This software is released under the PostgreSQL Licence
|
||||
//
|
||||
//////////////////////////////////////////////////////////////
|
||||
|
||||
export default function uplotOverride(theme) {
|
||||
return {
|
||||
'.uplot': {
|
||||
'& .u-legend': {
|
||||
display: 'none',
|
||||
}
|
||||
},
|
||||
'.uplot-tooltip': {
|
||||
position: 'absolute',
|
||||
fontSize: '0.9em',
|
||||
padding: '4px 8px',
|
||||
borderRadius: theme.shape.borderRadius,
|
||||
color: theme.palette.background.default,
|
||||
backgroundColor: theme.palette.text.primary,
|
||||
|
||||
'& .uplot-tooltip-label': {
|
||||
display: 'flex',
|
||||
gap: '4px',
|
||||
alignItems: 'center',
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
124
web/pgadmin/static/js/components/PgChart/StreamingChart.jsx
Normal file
124
web/pgadmin/static/js/components/PgChart/StreamingChart.jsx
Normal file
@@ -0,0 +1,124 @@
|
||||
import React, { useRef, useMemo } from 'react';
|
||||
import UplotReact from 'uplot-react';
|
||||
import { useResizeDetector } from 'react-resize-detector';
|
||||
import gettext from 'sources/gettext';
|
||||
import PropTypes from 'prop-types';
|
||||
|
||||
function tooltipPlugin(refreshRate) {
|
||||
let tooltipTopOffset = -20;
|
||||
let tooltipLeftOffset = 10;
|
||||
let tooltip;
|
||||
|
||||
function showTooltip() {
|
||||
if(!tooltip) {
|
||||
tooltip = document.createElement('div');
|
||||
tooltip.className = 'uplot-tooltip';
|
||||
tooltip.style.display = 'block';
|
||||
document.body.appendChild(tooltip);
|
||||
}
|
||||
}
|
||||
|
||||
function hideTooltip() {
|
||||
tooltip?.remove();
|
||||
tooltip = null;
|
||||
}
|
||||
|
||||
function setTooltip(u) {
|
||||
if(u.cursor.top <= 0) {
|
||||
hideTooltip();
|
||||
return;
|
||||
}
|
||||
showTooltip();
|
||||
let tooltipHtml=`<div>${(u.data[1].length-1-parseInt(u.legend.values[0]['_'])) * refreshRate + gettext(' seconds ago')}</div>`;
|
||||
for(let i=1; i<u.series.length; i++) {
|
||||
tooltipHtml += `<div class="uplot-tooltip-label"><div style="height:12px; width:12px; background-color:${u.series[i].stroke()}"></div> ${u.series[i].label}: ${u.legend.values[i]['_']}</div>`;
|
||||
}
|
||||
tooltip.innerHTML = tooltipHtml;
|
||||
|
||||
let overBBox = u.over.getBoundingClientRect();
|
||||
let tooltipBBox = tooltip.getBoundingClientRect();
|
||||
let left = (tooltipLeftOffset + u.cursor.left + overBBox.left);
|
||||
/* Should not outside the graph right */
|
||||
if((left+tooltipBBox.width) > overBBox.right) {
|
||||
left = left - tooltipBBox.width - tooltipLeftOffset*2;
|
||||
}
|
||||
tooltip.style.left = left + 'px';
|
||||
tooltip.style.top = (tooltipTopOffset + u.cursor.top + overBBox.top) + 'px';
|
||||
}
|
||||
|
||||
return {
|
||||
hooks: {
|
||||
setCursor: [
|
||||
u => {
|
||||
setTooltip(u);
|
||||
}
|
||||
],
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
export default function StreamingChart({xRange=75, data, options}) {
|
||||
const chartRef = useRef();
|
||||
const { width, height, ref:containerRef } = useResizeDetector();
|
||||
const defaultOptions = useMemo(()=>({
|
||||
title: '',
|
||||
width: width,
|
||||
height: height,
|
||||
padding: [10, 0, 10, 0],
|
||||
focus: {
|
||||
alpha: 0.3,
|
||||
},
|
||||
cursor: {
|
||||
drag: {
|
||||
setScale: false,
|
||||
}
|
||||
},
|
||||
series: [
|
||||
{},
|
||||
...data.datasets?.map((datum)=>({
|
||||
label: datum.label,
|
||||
stroke: datum.borderColor,
|
||||
width: options.lineBorderWidth ?? 1,
|
||||
points: { show: options.showDataPoints ?? false, size: datum.pointHitRadius*2 }
|
||||
}))
|
||||
],
|
||||
scales: {
|
||||
x: {
|
||||
time: false,
|
||||
}
|
||||
},
|
||||
axes: [
|
||||
{
|
||||
show: false,
|
||||
},
|
||||
],
|
||||
plugins: options.showTooltip ? [tooltipPlugin(data.refreshRate)] : [],
|
||||
}), [data.refreshRate, data?.datasets?.length, width, height, options]);
|
||||
|
||||
const initialState = [
|
||||
Array.from(new Array(xRange).keys()),
|
||||
...data.datasets?.map((d)=>{
|
||||
let ret = [...d.data];
|
||||
ret.reverse();
|
||||
return ret;
|
||||
}),
|
||||
];
|
||||
|
||||
chartRef.current?.setScale('x', {min: data.datasets[0]?.data?.length-xRange, max: data.datasets[0]?.data?.length-1});
|
||||
return (
|
||||
<div ref={containerRef} style={{width: '100%', height: '100%'}}>
|
||||
<UplotReact target={containerRef.current} options={defaultOptions} data={initialState} onCreate={(obj)=>chartRef.current=obj} />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
const propTypeData = PropTypes.shape({
|
||||
datasets: PropTypes.array,
|
||||
refreshRate: PropTypes.number.isRequired,
|
||||
});
|
||||
|
||||
StreamingChart.propTypes = {
|
||||
xRange: PropTypes.number.isRequired,
|
||||
data: propTypeData.isRequired,
|
||||
options: PropTypes.object,
|
||||
};
|
||||
Reference in New Issue
Block a user