From 8a5a4bc0674f0b1e55ecba37a6b6a4567bdbf1f2 Mon Sep 17 00:00:00 2001
From: Brandon McFarlin <6525520+Brandawg93@users.noreply.github.com>
Date: Sun, 29 Dec 2024 22:56:36 -0500
Subject: [PATCH] mui charts
---
__tests__/unit/app/page.test.tsx | 5 -
.../unit/client/components/gauge.test.tsx | 4 -
.../client/components/line-chart.test.tsx | 4 -
.../client/components/watts-chart.test.tsx | 4 -
package.json | 3 -
pnpm-lock.yaml | 42 ------
src/client/components/charts-container.tsx | 5 -
src/client/components/line-chart.tsx | 120 ++++++++----------
src/client/components/watts-chart.tsx | 106 +++++++---------
9 files changed, 105 insertions(+), 188 deletions(-)
diff --git a/__tests__/unit/app/page.test.tsx b/__tests__/unit/app/page.test.tsx
index c01473a..fe695bb 100644
--- a/__tests__/unit/app/page.test.tsx
+++ b/__tests__/unit/app/page.test.tsx
@@ -23,11 +23,6 @@ jest.mock('@tanstack/react-query', () => {
}
})
-jest.mock('react-chartjs-2', () => ({
- Line: () => null,
- Doughnut: () => null,
-}))
-
jest.mock('../../../src/app/actions', () => ({
getDevices: jest.fn(),
checkSettings: jest.fn(),
diff --git a/__tests__/unit/client/components/gauge.test.tsx b/__tests__/unit/client/components/gauge.test.tsx
index 5f0fe15..e25579a 100644
--- a/__tests__/unit/client/components/gauge.test.tsx
+++ b/__tests__/unit/client/components/gauge.test.tsx
@@ -2,10 +2,6 @@ import React from 'react'
import { render, fireEvent } from '@testing-library/react'
import Gauge from '@/client/components/gauge'
-jest.mock('react-chartjs-2', () => ({
- Doughnut: () => null,
-}))
-
describe('Gauge', () => {
it('renders', () => {
const { getByTestId } = render()
diff --git a/__tests__/unit/client/components/line-chart.test.tsx b/__tests__/unit/client/components/line-chart.test.tsx
index bf9c246..b64759d 100644
--- a/__tests__/unit/client/components/line-chart.test.tsx
+++ b/__tests__/unit/client/components/line-chart.test.tsx
@@ -3,10 +3,6 @@ import { render } from '@testing-library/react'
import LineChart from '@/client/components/line-chart'
import { DEVICE } from '@/common/types'
-jest.mock('react-chartjs-2', () => ({
- Line: () => null,
-}))
-
const device: DEVICE = {
vars: {
'input.voltage': {
diff --git a/__tests__/unit/client/components/watts-chart.test.tsx b/__tests__/unit/client/components/watts-chart.test.tsx
index 066d2f4..98db941 100644
--- a/__tests__/unit/client/components/watts-chart.test.tsx
+++ b/__tests__/unit/client/components/watts-chart.test.tsx
@@ -3,10 +3,6 @@ import { render } from '@testing-library/react'
import WattsChart from '@/client/components/watts-chart'
import { DEVICE } from '@/common/types'
-jest.mock('react-chartjs-2', () => ({
- Line: () => null,
-}))
-
const device: DEVICE = {
vars: {
'ups.realpower': {
diff --git a/package.json b/package.json
index 1f507c5..2e3ef04 100644
--- a/package.json
+++ b/package.json
@@ -38,8 +38,6 @@
"@mui/x-charts": "^7.23.2",
"@tanstack/react-query": "^5.62.8",
"@tanstack/react-table": "^8.20.6",
- "chart.js": "^4.4.7",
- "chartjs-plugin-annotation": "^3.1.0",
"i18next": "^24.1.2",
"i18next-browser-languagedetector": "^8.0.2",
"i18next-resources-to-backend": "^1.2.1",
@@ -48,7 +46,6 @@
"next": "^15.1.1",
"next-i18next": "^15.4.1",
"react": "^19.0.0",
- "react-chartjs-2": "^5.2.0",
"react-dom": "^19.0.0",
"react-i18next": "^15.2.0",
"react-icons": "^5.4.0",
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index 6aa70e8..df2df46 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -41,12 +41,6 @@ importers:
'@tanstack/react-table':
specifier: ^8.20.6
version: 8.20.6(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
- chart.js:
- specifier: ^4.4.7
- version: 4.4.7
- chartjs-plugin-annotation:
- specifier: ^3.1.0
- version: 3.1.0(chart.js@4.4.7)
i18next:
specifier: ^24.1.2
version: 24.1.2(typescript@5.7.2)
@@ -71,9 +65,6 @@ importers:
react:
specifier: ^19.0.0
version: 19.0.0
- react-chartjs-2:
- specifier: ^5.2.0
- version: 5.2.0(chart.js@4.4.7)(react@19.0.0)
react-dom:
specifier: ^19.0.0
version: 19.0.0(react@19.0.0)
@@ -845,9 +836,6 @@ packages:
'@jsdevtools/ono@7.1.3':
resolution: {integrity: sha512-4JQNk+3mVzK3xh2rqd6RB4J46qUR19azEHBneZyTZM+c456qOrbbM/5xcR8huNCCcbVt7+UmizG6GuUvPvKUYg==}
- '@kurkle/color@0.3.2':
- resolution: {integrity: sha512-fuscdXJ9G1qb7W8VdHi+IwRqij3lBkosAm4ydQtEmbY58OzHXqQhvlxqEkoz0yssNVn38bcpRWgA9PP+OGoisw==}
-
'@material-tailwind/react@2.1.10':
resolution: {integrity: sha512-xGU/mLDKDBp/qZ8Dp2XR7fKcTpDuFeZEBqoL9Bk/29kakKxNxjUGYSRHEFLsyOFf4VIhU6WGHdIS7tOA3QGJHA==}
peerDependencies:
@@ -1787,15 +1775,6 @@ packages:
character-reference-invalid@1.1.4:
resolution: {integrity: sha512-mKKUkUbhPpQlCOfIuZkvSEgktjPFIsZKRRbC6KWVEMvlzblj3i3asQv5ODsrwt0N3pHAEvjP8KTQPHkp0+6jOg==}
- chart.js@4.4.7:
- resolution: {integrity: sha512-pwkcKfdzTMAU/+jNosKhNL2bHtJc/sSmYgVbuGTEDhzkrhmyihmP7vUc/5ZK9WopidMDHNe3Wm7jOd/WhuHWuw==}
- engines: {pnpm: '>=8'}
-
- chartjs-plugin-annotation@3.1.0:
- resolution: {integrity: sha512-EkAed6/ycXD/7n0ShrlT1T2Hm3acnbFhgkIEJLa0X+M6S16x0zwj1Fv4suv/2bwayCT3jGPdAtI9uLcAMToaQQ==}
- peerDependencies:
- chart.js: '>=4.0.0'
-
chokidar@3.6.0:
resolution: {integrity: sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==}
engines: {node: '>= 8.10.0'}
@@ -3778,12 +3757,6 @@ packages:
resolution: {integrity: sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==}
hasBin: true
- react-chartjs-2@5.2.0:
- resolution: {integrity: sha512-98iN5aguJyVSxp5U3CblRLH67J8gkfyGNbiK3c+l1QI/G4irHMPQw44aEPmjVag+YKTyQ260NcF82GTQ3bdscA==}
- peerDependencies:
- chart.js: ^4.1.1
- react: ^16.8.0 || ^17.0.0 || ^18.0.0
-
react-copy-to-clipboard@5.1.0:
resolution: {integrity: sha512-k61RsNgAayIJNoy9yDsYzDe/yAZAzEbEgcz3DZMhF686LEyukcE1hzurxe85JandPUG+yTfGVFzuEw3xt8WP/A==}
peerDependencies:
@@ -5455,8 +5428,6 @@ snapshots:
'@jsdevtools/ono@7.1.3': {}
- '@kurkle/color@0.3.2': {}
-
'@material-tailwind/react@2.1.10(react-dom@19.0.0(react@19.0.0))(react@19.0.0)':
dependencies:
'@floating-ui/react': 0.19.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
@@ -6771,14 +6742,6 @@ snapshots:
character-reference-invalid@1.1.4: {}
- chart.js@4.4.7:
- dependencies:
- '@kurkle/color': 0.3.2
-
- chartjs-plugin-annotation@3.1.0(chart.js@4.4.7):
- dependencies:
- chart.js: 4.4.7
-
chokidar@3.6.0:
dependencies:
anymatch: 3.1.3
@@ -9001,11 +8964,6 @@ snapshots:
strip-json-comments: 2.0.1
optional: true
- react-chartjs-2@5.2.0(chart.js@4.4.7)(react@19.0.0):
- dependencies:
- chart.js: 4.4.7
- react: 19.0.0
-
react-copy-to-clipboard@5.1.0(react@19.0.0):
dependencies:
copy-to-clipboard: 3.3.3
diff --git a/src/client/components/charts-container.tsx b/src/client/components/charts-container.tsx
index e477d47..907625b 100644
--- a/src/client/components/charts-container.tsx
+++ b/src/client/components/charts-container.tsx
@@ -1,15 +1,10 @@
'use client'
-import 'chart.js/auto'
import React from 'react'
-import { Chart } from 'chart.js'
-import annotationPlugin from 'chartjs-plugin-annotation'
import { VARS, DeviceData } from '@/common/types'
import LineChart from '@/client/components/line-chart'
import WattsChart from '@/client/components/watts-chart'
-Chart.register(annotationPlugin)
-
type Props = {
vars: VARS
data: DeviceData
diff --git a/src/client/components/line-chart.tsx b/src/client/components/line-chart.tsx
index 2d6345c..03037d6 100644
--- a/src/client/components/line-chart.tsx
+++ b/src/client/components/line-chart.tsx
@@ -1,9 +1,17 @@
import React, { useEffect, useState, useRef, useContext } from 'react'
-import { Line } from 'react-chartjs-2'
import { Card } from '@material-tailwind/react'
-
+import { ResponsiveChartContainer } from '@mui/x-charts/ResponsiveChartContainer'
+import { ChartsLegend } from '@mui/x-charts/ChartsLegend'
+import { ChartsGrid } from '@mui/x-charts/ChartsGrid'
+import { ChartsReferenceLine } from '@mui/x-charts/ChartsReferenceLine'
+import { LinePlot, MarkPlot } from '@mui/x-charts/LineChart'
+import { ChartsXAxis } from '@mui/x-charts/ChartsXAxis'
+import { ChartsYAxis } from '@mui/x-charts/ChartsYAxis'
+import { ThemeProvider, createTheme } from '@mui/material/styles'
+import CssBaseline from '@mui/material/CssBaseline'
import { useTranslation } from 'react-i18next'
import { LanguageContext } from '@/client/context/language'
+import { ThemeContext } from '../context/theme'
type Props = {
id: string
@@ -16,6 +24,12 @@ type Props = {
export default function LineChart(props: Props) {
const { id, inputVoltage, inputVoltageNominal, outputVoltage, updated } = props
const lng = useContext(LanguageContext)
+ const { theme } = useContext(ThemeContext)
+ const darkTheme = createTheme({
+ palette: {
+ mode: theme,
+ },
+ })
const { t } = useTranslation(lng)
const [inputVoltageData, setInputVoltageData] = useState>([])
const [outputVoltageData, setOutputVoltageData] = useState>([])
@@ -35,69 +49,47 @@ export default function LineChart(props: Props) {
}, [id, inputVoltage, outputVoltage, updated])
return (
-
- ''),
- datasets: [
- {
- label: t('lineChart.inputVoltage'),
- data: inputVoltageData,
- fill: false,
- borderColor: 'rgb(8, 143, 143)',
- tension: 0.1,
- },
+
+
+
+ index) }]}
+ yAxis={[
{
- label: t('lineChart.outputVoltage'),
- data: outputVoltageData,
- fill: false,
- borderColor: 'rgb(255, 83, 73)',
- tension: 0.1,
- },
- {
- label: t('lineChart.nominalInputVoltage'),
- data: [],
- borderColor: 'black',
- borderDash: [6, 6],
- borderDashOffset: 0,
- borderWidth: 3,
- backgroundColor: 'rgb(0, 0, 0, 0)',
- },
- ],
- }}
- options={{
- animation: {
- duration: window.matchMedia('(prefers-reduced-motion: no-preference)').matches ? 1000 : 0,
- },
- scales: {
- y: {
- ticks: {
- callback: (tickValue: string | number) => `${tickValue}V`,
- },
- },
- },
- maintainAspectRatio: false,
- plugins: {
- annotation: {
- annotations: {
- nominal: {
- type: 'line',
- borderColor: 'black',
- borderDash: [6, 6],
- borderDashOffset: 0,
- borderWidth: 3,
- scaleID: 'y',
- value: inputVoltageNominal,
- },
- },
+ scaleType: 'linear',
+ valueFormatter: (value: number) => `${value}V`,
+ min: inputVoltageNominal
+ ? Math.min(...inputVoltageData, ...outputVoltageData, inputVoltageNominal)
+ : Math.min(...inputVoltageData, ...outputVoltageData),
+ max: inputVoltageNominal
+ ? Math.max(...inputVoltageData, ...outputVoltageData, inputVoltageNominal)
+ : Math.max(...inputVoltageData, ...outputVoltageData),
},
- },
- }}
- />
-
+ ]}
+ >
+
+
+ {inputVoltageNominal && (
+
+ )}
+
+
+
+
+
+
+
)
}
diff --git a/src/client/components/watts-chart.tsx b/src/client/components/watts-chart.tsx
index e94c732..24b6ba5 100644
--- a/src/client/components/watts-chart.tsx
+++ b/src/client/components/watts-chart.tsx
@@ -1,9 +1,17 @@
import React, { useEffect, useState, useRef, useContext } from 'react'
-import { Line } from 'react-chartjs-2'
import { Card } from '@material-tailwind/react'
+import { ResponsiveChartContainer } from '@mui/x-charts/ResponsiveChartContainer'
+import { ChartsLegend } from '@mui/x-charts/ChartsLegend'
+import { ChartsGrid } from '@mui/x-charts/ChartsGrid'
+import { ChartsReferenceLine } from '@mui/x-charts/ChartsReferenceLine'
+import { LinePlot, MarkPlot } from '@mui/x-charts/LineChart'
+import { ChartsXAxis } from '@mui/x-charts/ChartsXAxis'
+import { ChartsYAxis } from '@mui/x-charts/ChartsYAxis'
+import { ThemeProvider, createTheme } from '@mui/material/styles'
+import CssBaseline from '@mui/material/CssBaseline'
import { useTranslation } from 'react-i18next'
-
import { LanguageContext } from '@/client/context/language'
+import { ThemeContext } from '../context/theme'
type Props = {
id: string
@@ -17,6 +25,12 @@ export default function WattsChart(props: Props) {
const [dataPoints, setDataPoints] = useState>([])
const prevDataRef = useRef(id)
const lng = useContext(LanguageContext)
+ const { theme } = useContext(ThemeContext)
+ const darkTheme = createTheme({
+ palette: {
+ mode: theme,
+ },
+ })
const { t } = useTranslation(lng)
useEffect(() => {
@@ -30,62 +44,40 @@ export default function WattsChart(props: Props) {
}, [id, realpower, updated])
return (
-
- ''),
- datasets: [
- {
- label: t('wattsChart.realpower'),
- data: dataPoints,
- fill: false,
- borderColor: 'rgb(8, 143, 143)',
- tension: 0.1,
- },
+
+
+
+ index) }]}
+ yAxis={[
{
- label: t('wattsChart.nominalRealpower'),
- data: [],
- borderColor: 'black',
- borderDash: [6, 6],
- borderDashOffset: 0,
- borderWidth: 3,
- backgroundColor: 'rgb(0, 0, 0, 0)',
- },
- ],
- }}
- options={{
- animation: {
- duration: window.matchMedia('(prefers-reduced-motion: no-preference)').matches ? 1000 : 0,
- },
- scales: {
- y: {
- ticks: {
- callback: (tickValue: string | number) => `${tickValue}W`,
- },
- },
- },
- maintainAspectRatio: false,
- plugins: {
- annotation: {
- annotations: {
- nominal: {
- type: 'line',
- borderColor: 'black',
- borderDash: [6, 6],
- borderDashOffset: 0,
- borderWidth: 3,
- scaleID: 'y',
- value: realpowerNominal,
- },
- },
+ scaleType: 'linear',
+ valueFormatter: (value: number) => `${value}V`,
+ min: realpowerNominal ? Math.min(...dataPoints, realpowerNominal) : Math.min(...dataPoints),
+ max: realpowerNominal ? Math.max(...dataPoints, realpowerNominal) : Math.max(...dataPoints),
},
- },
- }}
- />
-
+ ]}
+ >
+
+
+ {realpowerNominal && (
+
+ )}
+
+
+
+
+
+
+
)
}