Created
March 26, 2025 10:01
-
-
Save bitmorse/836b895d04aa44996f29bf9ec3e9c1f1 to your computer and use it in GitHub Desktop.
InfluxDB Plot HTML to embed into Nocobase Iframe
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!DOCTYPE html> | |
<html lang="en"> | |
<head> | |
<meta charset="utf-8"> | |
<title>OpenWRT Load Monitor</title> | |
<script crossorigin src="https://unpkg.com/react@17/umd/react.development.js"></script> | |
<script crossorigin src="https://unpkg.com/react-dom@17/umd/react-dom.development.js"></script> | |
<script crossorigin src="https://unpkg.com/@influxdata/giraffe"></script> | |
<script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script> | |
<style> | |
body { | |
font-family: Arial, sans-serif; | |
margin: 20px; | |
} | |
h1 { | |
color: #333; | |
} | |
.loading { | |
margin: 40px; | |
font-size: 18px; | |
color: #666; | |
} | |
.error { | |
margin: 40px; | |
font-size: 18px; | |
color: #d32f2f; | |
} | |
</style> | |
</head> | |
<body> | |
<h1>OpenWRT Load Monitor</h1> | |
<main id="root"></main> | |
<script type="text/javascript"> | |
class PlotRenderer extends React.Component { | |
constructor(props) { | |
super(props); | |
this.state = { | |
loading: true, | |
error: null, | |
fluxResponse: null | |
}; | |
} | |
componentDidMount() { | |
this.fetchData(); | |
this.refreshInterval = setInterval(() => this.fetchData(), 60000); | |
} | |
componentWillUnmount() { | |
if (this.refreshInterval) { | |
clearInterval(this.refreshInterval); | |
} | |
} | |
fetchData() { | |
const url = 'YOUR INFLUX URL'; | |
const org = 'YOUR INFLUX ORG'; | |
const token = 'YOUR INFLUX RO TOKEN'; //READ ONLY!!!!!! | |
const query = ` | |
from(bucket: "AVI") | |
|> range(start: -24h) | |
|> filter(fn: (r) => r._measurement == "openwrt_7628") | |
|> filter(fn: (r) => r._field == "load") | |
|> yield(name: "load") | |
`; | |
axios({ | |
method: 'POST', | |
url: url, | |
headers: { | |
'Authorization': `Token ${token}`, | |
'Content-Type': 'application/json', | |
'Accept': 'application/csv' | |
}, | |
params: { | |
org | |
}, | |
data: { | |
query | |
} | |
}) | |
.then(response => { | |
console.log("Data received:", response.data); | |
// Add the missing headers that Giraffe expects | |
const headers = [ | |
"#datatype,string,long,dateTime:RFC3339,dateTime:RFC3339,dateTime:RFC3339,double,string,string,string,string", | |
"#group,false,false,true,true,false,false,true,true,true,true", | |
"#default,_result,,,,,,,,," | |
].join("\n"); | |
// Combine headers with the data | |
const completeData = headers + "\n" + response.data; | |
console.log("Complete data with headers:", completeData); | |
this.setState({ | |
loading: false, | |
fluxResponse: completeData | |
}); | |
}) | |
.catch(error => { | |
console.error("Error fetching data:", error); | |
this.setState({ | |
loading: false, | |
error: `Error fetching data: ${error.message}` | |
}); | |
}); | |
} | |
render() { | |
const { loading, error, fluxResponse } = this.state; | |
if (loading) { | |
return React.createElement('div', { className: 'loading' }, 'Loading data...'); | |
} | |
if (error) { | |
return React.createElement('div', { className: 'error' }, error); | |
} | |
const style = { | |
width: "calc(70vw - 20px)", | |
height: "calc(70vh - 20px)", | |
margin: "40px", | |
}; | |
// If we have data, create a plot with it | |
if (fluxResponse) { | |
try { | |
// Create a simple line layer | |
const lineLayer = { | |
type: "line", | |
x: "_time", | |
y: "_value", | |
colors: ["#31C0F6"], | |
lineWidth: 2 | |
}; | |
// Create the config using the fluxResponse with added headers | |
const config = { | |
fluxResponse, | |
layers: [lineLayer] | |
}; | |
// Create the Plot component | |
const Plot = React.createElement(Giraffe.Plot, {config}, null); | |
return React.createElement('div', {style}, Plot); | |
} catch (e) { | |
console.error("Error creating plot:", e); | |
return React.createElement('div', { className: 'error' }, | |
`Error creating plot: ${e.message}. Check console for details.`); | |
} | |
} | |
return React.createElement('div', null, 'No data available'); | |
} | |
} | |
// Render the component | |
ReactDOM.render( | |
React.createElement(PlotRenderer), | |
document.getElementById('root') | |
); | |
</script> | |
</body> | |
</html> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment