Improved UI
This commit is contained in:
+30
-3
@@ -3,12 +3,13 @@ import { useState, useMemo, useEffect } from 'preact/hooks';
|
||||
import InterfaceList from './InterfaceList';
|
||||
import Canvas from './Canvas';
|
||||
import PlotPanel from './PlotPanel';
|
||||
import type { PlotSignal } from './PlotPanel';
|
||||
import type { PlotSignal, PlotSignalStyle } from './PlotPanel';
|
||||
import { wsClient } from './lib/ws';
|
||||
import { parseInterface } from './lib/xml';
|
||||
import type { Interface, SignalRef } from './lib/types';
|
||||
import ContextualHelp from './ContextualHelp';
|
||||
import HelpModal from './HelpModal';
|
||||
import ZoomControl from './ZoomControl';
|
||||
|
||||
interface Props {
|
||||
onEdit?: (iface?: Interface) => void;
|
||||
@@ -34,6 +35,22 @@ export default function ViewMode({ onEdit, initialInterface }: Props) {
|
||||
const [showTimeNav, setShowTimeNav] = useState(false);
|
||||
const [viewTab, setViewTab] = useState<ViewTab>('hmi');
|
||||
const [plotSignals, setPlotSignals] = useState<PlotSignal[]>([]);
|
||||
const [leftW, setLeftW] = useState(220);
|
||||
|
||||
function startResize(e: MouseEvent) {
|
||||
e.preventDefault();
|
||||
const startX = e.clientX;
|
||||
const startW = leftW;
|
||||
function onMove(mv: MouseEvent) {
|
||||
setLeftW(Math.max(140, startW + mv.clientX - startX));
|
||||
}
|
||||
function onUp() {
|
||||
window.removeEventListener('mousemove', onMove);
|
||||
window.removeEventListener('mouseup', onUp);
|
||||
}
|
||||
window.addEventListener('mousemove', onMove);
|
||||
window.addEventListener('mouseup', onUp);
|
||||
}
|
||||
|
||||
function openHelp(section = 'start') { setHelpSection(section); setShowHelp(true); }
|
||||
|
||||
@@ -100,7 +117,8 @@ export default function ViewMode({ onEdit, initialInterface }: Props) {
|
||||
const already = plotSignals.some(s => `${s.ref.ds}\0${s.ref.name}` === key);
|
||||
if (!already) {
|
||||
const color = PLOT_COLORS[plotSignals.length % PLOT_COLORS.length];
|
||||
setPlotSignals(prev => [...prev, { ref, color }]);
|
||||
const style: PlotSignalStyle = { color, lineWidth: 1.5, lineDash: [], markerSize: 5 };
|
||||
setPlotSignals(prev => [...prev, { ref, style }]);
|
||||
}
|
||||
setViewTab('plot');
|
||||
}
|
||||
@@ -109,6 +127,12 @@ export default function ViewMode({ onEdit, initialInterface }: Props) {
|
||||
setPlotSignals(prev => prev.filter(s => !(s.ref.ds === ref.ds && s.ref.name === ref.name)));
|
||||
}
|
||||
|
||||
function updateSignalStyle(ref: SignalRef, style: PlotSignalStyle) {
|
||||
setPlotSignals(prev => prev.map(s =>
|
||||
s.ref.ds === ref.ds && s.ref.name === ref.name ? { ...s, style } : s
|
||||
));
|
||||
}
|
||||
|
||||
const isLive = timeRange === null;
|
||||
|
||||
return (
|
||||
@@ -145,6 +169,7 @@ export default function ViewMode({ onEdit, initialInterface }: Props) {
|
||||
>
|
||||
📖
|
||||
</button>
|
||||
<ZoomControl />
|
||||
<button
|
||||
class="btn-edit"
|
||||
onClick={() => onEdit?.(currentInterface ?? undefined)}
|
||||
@@ -195,6 +220,7 @@ export default function ViewMode({ onEdit, initialInterface }: Props) {
|
||||
onLoad={handleLoad}
|
||||
onEdit={onEdit}
|
||||
onEditId={handleEditById}
|
||||
width={leftW}
|
||||
onSelect={async (id) => {
|
||||
try {
|
||||
const res = await fetch(`/api/v1/interfaces/${encodeURIComponent(id)}`);
|
||||
@@ -206,6 +232,7 @@ export default function ViewMode({ onEdit, initialInterface }: Props) {
|
||||
}
|
||||
}}
|
||||
/>
|
||||
<div class="panel-resize-handle" onMouseDown={startResize} />
|
||||
|
||||
<div class="view-content-area">
|
||||
{/* Tab bar */}
|
||||
@@ -234,7 +261,7 @@ export default function ViewMode({ onEdit, initialInterface }: Props) {
|
||||
/>
|
||||
</div>
|
||||
<div style={`display:${viewTab === 'plot' ? 'contents' : 'none'}`}>
|
||||
<PlotPanel signals={plotSignals} onRemove={removeFromPlot} />
|
||||
<PlotPanel signals={plotSignals} onRemove={removeFromPlot} onStyleChange={updateSignalStyle} />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user