diff --git a/uiserver/src/components/Chart.js b/uiserver/src/components/Chart.js
index 089ecf3..e8c22f8 100644
--- a/uiserver/src/components/Chart.js
+++ b/uiserver/src/components/Chart.js
@@ -9,7 +9,8 @@ export default class Chart extends Component {
super(props);
this.state = {
data: [],
- loading: true
+ loading: true,
+ hiddenSeries: {} // { seriesId: true/false }
};
this.interval = null;
}
@@ -219,15 +220,41 @@ export default class Chart extends Component {
return { min: axisMin, max: axisMax };
}
+ toggleSeries = (seriesId) => {
+ this.setState(prev => ({
+ hiddenSeries: {
+ ...prev.hiddenSeries,
+ [seriesId]: !prev.hiddenSeries[seriesId]
+ }
+ }));
+ };
+
render() {
- const { loading, data } = this.state;
+ const { loading, data, hiddenSeries } = this.state;
const { channelConfig, windowEnd, range } = this.props;
const effectiveChannels = this.getEffectiveChannels(this.props);
if (loading) return ;
if (effectiveChannels.length === 0) return No channels selected.;
- const series = effectiveChannels.map(id => {
+ // Build legend config (all channels, for rendering custom legend)
+ const legendItems = effectiveChannels.map(id => {
+ let label = id;
+ let color = '#888';
+ if (channelConfig) {
+ const item = channelConfig.find(c => c.id === id);
+ if (item) {
+ if (item.alias) label = item.alias;
+ if (item.color) color = item.color;
+ }
+ }
+ return { id, label, color, hidden: !!hiddenSeries[id] };
+ });
+
+ // Filter out hidden series
+ const visibleChannels = effectiveChannels.filter(id => !hiddenSeries[id]);
+
+ const series = visibleChannels.map(id => {
// Find alias and axis if config exists
let label = id;
let yAxisKey = 'left';
@@ -281,6 +308,40 @@ export default class Chart extends Component {
return (
+ {/* Custom Interactive Legend */}
+
+ {legendItems.map(item => (
+ this.toggleSeries(item.id)}
+ sx={{
+ display: 'flex',
+ alignItems: 'center',
+ gap: 0.5,
+ cursor: 'pointer',
+ opacity: item.hidden ? 0.4 : 1,
+ textDecoration: item.hidden ? 'line-through' : 'none',
+ transition: 'opacity 0.2s',
+ userSelect: 'none',
+ '&:hover': { opacity: item.hidden ? 0.6 : 0.8 },
+ }}
+ >
+
+
+ {item.label}
+
+
+ ))}
+