diff --git a/frontend/src/App.tsx b/frontend/src/App.tsx index 39e3c8831..b73aa5b25 100644 --- a/frontend/src/App.tsx +++ b/frontend/src/App.tsx @@ -28,7 +28,7 @@ import _ from "lodash"; import Markdown from "react-markdown"; import remarkGfm from "remark-gfm"; -import StatusBar from "./components/StatusBar"; +import StatusBar, { StatusBarSpacer } from "./components/StatusBar"; import ErrorMessage from "./components/ErrorMessage"; import DataProcessingPlots from "./components/DataProcessingPlots"; import MeasurementStatistics from "./components/MeasurementStatistics"; @@ -164,7 +164,7 @@ function App() { - + @@ -270,7 +270,7 @@ function App() { sx={{ width: drawerWidth, flexShrink: 0, '& .MuiDrawer-paper': { width: drawerWidth, boxSizing: 'border-box', bgcolor: drawer.bg, borderRight: 'none' } }}> - + {sections.map((sec, i) => ( )} - + {activeItem.render?.()} diff --git a/frontend/src/components/DataCollection.tsx b/frontend/src/components/DataCollection.tsx index 6bcd6515a..73cf2990e 100644 --- a/frontend/src/components/DataCollection.tsx +++ b/frontend/src/components/DataCollection.tsx @@ -94,7 +94,7 @@ function DataCollection({frame_time_us}: MyProps) { value={tokens} sx={{width:"90%"}} /> - + { @@ -137,7 +137,7 @@ function DataCollection({frame_time_us}: MyProps) { default={s.images_per_file} /> - + { @@ -196,7 +196,7 @@ function DataCollection({frame_time_us}: MyProps) { {mode === 'rotation' && ( - + setGoniometer(prev => ({...prev, start: val}))} @@ -220,7 +220,7 @@ function DataCollection({frame_time_us}: MyProps) { )} {mode === 'grid' && ( - + setGrid(prev => ({...prev, n_fast: val}))} diff --git a/frontend/src/components/DataProcessingPlot.tsx b/frontend/src/components/DataProcessingPlot.tsx index bdd485a1a..539b8badd 100644 --- a/frontend/src/components/DataProcessingPlot.tsx +++ b/frontend/src/components/DataProcessingPlot.tsx @@ -3,11 +3,20 @@ import {ReactNode} from 'react'; import {useQuery} from "@tanstack/react-query"; import ShowChartIcon from "@mui/icons-material/ShowChart"; import {azint_unit, plot_type, plot_unit_x} from "../client"; -import {getPreviewPlotOptions} from "../client/@tanstack/react-query.gen"; +import {getConfigRugnuxOptions, getPreviewPlotOptions, getRugnuxStatusOptions} from "../client/@tanstack/react-query.gen"; import MultiLinePlotWrapper from "./MultiLinePlotWrapper"; import EmptyState from "./EmptyState"; import {useTokenRequired} from "../auth"; +// Whether rugnux live is on a run: the per-image values then come with its first pass over the images, +// not image by image. The same queries the rugnux card polls, so this costs no request of its own. +function useRugnuxRunning() { + const {data: settings} = useQuery({...getConfigRugnuxOptions(), refetchInterval: 2000}); + const enabled = settings?.enable === true; + const {data: s} = useQuery({...getRugnuxStatusOptions(), refetchInterval: 1000, enabled}); + return enabled && s?.state === "Running"; +} + type MyProps = { type: plot_type; binning: number; @@ -108,6 +117,7 @@ function DataProcessingPlot({type, binning, angle, azint}: MyProps) { }); const tokenRequired = useTokenRequired(); + const rugnuxRunning = useRugnuxRunning(); if (isError || (plots === undefined) @@ -116,6 +126,11 @@ function DataProcessingPlot({type, binning, angle, azint}: MyProps) { return } text={tokenRequired ? "Dataset token required (key button in the top bar)" : "No plots available"}/>; + // a plot with no points (an image without a value is left out): nothing measured yet + if (plots.plot.every(d => d.y.length === 0)) + return } + text={rugnuxRunning ? "Per-image values come with rugnux's first pass over the images" : "No values yet"}/>; + let data: PlotlyData = []; if ((plots.plot[0].z !== undefined) && (plots.plot[0].z.length > 0)) { diff --git a/frontend/src/components/DataProcessingPlots.tsx b/frontend/src/components/DataProcessingPlots.tsx index bff4a20bf..8dbe43bd1 100644 --- a/frontend/src/components/DataProcessingPlots.tsx +++ b/frontend/src/components/DataProcessingPlots.tsx @@ -31,11 +31,12 @@ function DataProcessingPlots({type: initialType, height}: MyProps) { setBinning(String(event.target.value).toString()); }; - return - + // On a phone the toolbar wraps, the select above the three controls, and the card takes the height it needs + return + - - + +