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} + + + ))} +