Skip to content

Commit

Permalink
Merge pull request #569 from ral-facilities/DSEGOG-57-plots-skip-non-…
Browse files Browse the repository at this point in the history
…working-hours

DSEGOG-57 skip non-working hours toggle for plots
  • Loading branch information
louise-davies authored Feb 6, 2025
2 parents 0fe0d77 + 29678ac commit 8029c56
Show file tree
Hide file tree
Showing 26 changed files with 361 additions and 52 deletions.
70 changes: 63 additions & 7 deletions e2e/mocked/plotting.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ test('plots a time vs shotnum graph and change the plot colour', async ({

await popup.locator('label:has-text("Title")').fill('Test time plot');

await popup.locator('[aria-label="line chart"]').click();
await popup.locator('[aria-label="Line Chart"]').click();

await popup.locator('label:has-text("Search all channels")').fill('Shot Num');

Expand Down Expand Up @@ -241,7 +241,7 @@ test('user can add from and to dates to timestamp on x-axis', async ({

await popup.locator('label:has-text("Title")').fill('Test time plot');

await popup.locator('[aria-label="line chart"]').click();
await popup.locator('[aria-label="Line Chart"]').click();

await popup.locator('label:has-text("Search all channels")').fill('Shot Num');

Expand Down Expand Up @@ -316,7 +316,7 @@ test('user can change line style of plotted channels', async ({ page }) => {
page.locator('text=Create a plot').click(),
]);

await popup.locator('[aria-label="line chart"]').click();
await popup.locator('[aria-label="Line Chart"]').click();

await popup.locator('label:has-text("Search all channels")').fill('ABCDE');

Expand Down Expand Up @@ -363,7 +363,7 @@ test('user can change the marker style and size of plotted channels', async ({
page.locator('text=Create a plot').click(),
]);

await popup.locator('[aria-label="line chart"]').click();
await popup.locator('[aria-label="Line Chart"]').click();

await popup.locator('label:has-text("Search all channels")').fill('Shot Num');

Expand Down Expand Up @@ -420,7 +420,7 @@ test('changes to and from dateTimes to use 0 seconds and 59 seconds respectively

await popup.locator('label:has-text("Title")').fill('Test time plot');

await popup.locator('[aria-label="line chart"]').click();
await popup.locator('[aria-label="Line Chart"]').click();

await popup.locator('label:has-text("Search all channels")').fill('Shot Num');

Expand Down Expand Up @@ -461,7 +461,7 @@ test('user can change the line width of plotted channels', async ({ page }) => {
page.locator('text=Create a plot').click(),
]);

await popup.locator('[aria-label="line chart"]').click();
await popup.locator('[aria-label="Line Chart"]').click();

await popup.locator('label:has-text("Search all channels")').fill('ABCDE');

Expand Down Expand Up @@ -527,7 +527,7 @@ test('user can plot channels on the right y axis', async ({ page }) => {
page.locator('text=Create a plot').click(),
]);

await popup.locator('[aria-label="line chart"]').click();
await popup.locator('[aria-label="Line Chart"]').click();

// users can add channels to the right y axis directly when "right" is selected as the axis
await popup.locator('text=Right').click();
Expand Down Expand Up @@ -677,3 +677,59 @@ test('scalar functions can be plotted', async ({ page }) => {
await popup.locator('label:has-text("Search")').fill('a');
await popup.getByRole('option', { name: 'a', exact: true });
});

test('user can skip non-business hours on a timeseries plot', async ({
page,
}) => {
await page.goto('/');

// MSW wont start immediately here, so wait for page to load first
await expect(page.locator('text=Plots')).toBeVisible();

await page.evaluate(async () => {
const { msw } = window;

const response = await fetch('/records');
const responseBody = await response.json();

const modifiedRecordsJson = responseBody.map((record, i) => {
const newRecord = JSON.parse(JSON.stringify(record));
const date = new Date(newRecord.metadata.timestamp);
date.setHours(i % 2 !== 0 ? 12 : 0); // set some timestamps to working hours and some to non-working hours
newRecord.metadata.timestamp = date
.toLocaleString('sv-SE')
.replace(' ', 'T');
return newRecord;
});

msw.worker.use(
msw.http.get('/records', async () =>
msw.HttpResponse.json(modifiedRecordsJson, { status: 200 })
)
);
});

await page.locator('text=Plots').click();

// open up popup
const [popup] = await Promise.all([
page.waitForEvent('popup'),
page.locator('text=Create a plot').click(),
]);

await popup.locator('label:has-text("Search all channels")').fill('Shot Num');

await popup.getByRole('option', { name: 'Shot Number', exact: true }).click();

await popup
.getByRole('checkbox', { name: 'Skip Non-Business Hours' })
.click();

await popup.locator('[aria-label="close settings"]').click();

// wait for open settings button to be visible i.e. menu is fully closed
await popup.locator('[aria-label="open settings"]').click({ trial: true });

const chart = await popup.locator('.plotly-chart');
await expect(chart).toHaveScreenshot({ maxDiffPixels: 150 });
});
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 1 addition & 1 deletion e2e/real/plotting.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ test('plots a time vs channel graph', async ({ page }) => {

await popup.locator('label:has-text("Title")').fill('Test time plot');

await popup.locator('[aria-label="line chart"]').click();
await popup.locator('[aria-label="Line Chart"]').click();

await popup.locator('label:has-text("Search all channels")').fill('209');

Expand Down
1 change: 1 addition & 0 deletions public/operationsgateway-settings.example.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
{
"apiUrl": "",
"recordLimitWarning": -1,
"workingHours": { "start": 9, "end": 18 },
"routes": [
{
"section": "OperationsGateway",
Expand Down
11 changes: 11 additions & 0 deletions src/plotting/__snapshots__/plot.component.test.tsx.snap
Original file line number Diff line number Diff line change
Expand Up @@ -76,3 +76,14 @@ exports[`Plot component > updates layout and data options correctly (linear axes
/>
</DocumentFragment>
`;

exports[`Plot component > updates layout object correctly by by setting rangebreaks for skip business hours feature 1`] = `
<DocumentFragment>
<div
class="plotly-chart"
data-config="{"scrollZoom":true,"displaylogo":false,"displayModeBar":false,"responsive":true,"showAxisDragHandles":false,"showTips":false}"
data-data="[{"type":"scatter","mode":"markers","name":"undefined","x":[1,2,3],"y":[2,3,4],"yaxis":"y","marker":{"color":"colour-0","opacity":1,"size":6,"symbol":"circle","line":{"color":"colour-0","width":1}},"line":{"color":"colour-0","width":3,"dash":"solid"},"showlegend":true,"hovertemplate":"(%{x|%Y-%m-%d %H:%M:%S}, %{y}) undefined<extra></extra>"},{"type":"scatter","mode":"markers","name":"undefined","x":[2,4,6],"y":[4,6,8],"yaxis":"y","marker":{"color":"colour-1","opacity":1,"size":6,"symbol":"circle","line":{"color":"colour-1","width":1}},"line":{"color":"colour-1","width":3,"dash":"solid"},"showlegend":true,"hovertemplate":"(%{x|%Y-%m-%d %H:%M:%S}, %{y}) undefined<extra></extra>"},{"type":"scatter","mode":"markers","name":"undefined","x":[3,6,9],"y":[6,9,12],"yaxis":"y","marker":{"color":"colour-2","opacity":1,"size":6,"symbol":"circle","line":{"color":"colour-2","width":1}},"line":{"color":"colour-2","width":3,"dash":"solid"},"showlegend":true,"hovertemplate":"(%{x|%Y-%m-%d %H:%M:%S}, %{y}) undefined<extra></extra>"}]"
data-layout="{"title":{"text":"scatter plot","automargin":true,"yref":"paper"},"margin":{"l":0,"r":0,"b":0,"t":0},"uirevision":"false","paper_bgcolor":"rgba(0, 0, 0, 0)","plot_bgcolor":"rgba(0, 0, 0, 0)","font":{"color":"#444"},"legend":{"orientation":"h","x":0.5,"yanchor":"bottom","xanchor":"center","yref":"container"},"xaxis":{"title":{"text":"timestamp","font":{"color":"#444"}},"type":"date","showgrid":true,"range":[null,null],"rangebreaks":[{"pattern":"day of week","bounds":["sat","mon"]},{"pattern":"hour","bounds":[18,9]}],"color":"#eee","gridcolor":"#eee","tickfont":{"color":"#444"},"automargin":true,"exponentformat":"none"},"yaxis":{"title":{"font":{"color":"#444"}},"type":"linear","showgrid":true,"visible":true,"range":[null,null],"color":"#eee","gridcolor":"#eee","tickfont":{"color":"#444"},"automargin":true,"exponentformat":"none"},"yaxis2":{"title":{"font":{"color":"#444"}},"type":"log","visible":false,"side":"right","overlaying":"y","showgrid":true,"range":[null,null],"color":"#eee","gridcolor":"#eee","tickfont":{"color":"#444"},"automargin":true,"exponentformat":"none"}}"
/>
</DocumentFragment>
`;
11 changes: 11 additions & 0 deletions src/plotting/plot.component.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@ describe('Plot component', () => {
viewReset: false,
gridVisible: true,
axesLabelsVisible: true,
workingHours: { start: 9, end: 18 },
skipNonBusinessHours: false,
};
});

Expand Down Expand Up @@ -153,6 +155,15 @@ describe('Plot component', () => {
expect(asFragment()).toMatchSnapshot();
});

it('updates layout object correctly by by setting rangebreaks for skip business hours feature', () => {
const { rerender, asFragment } = render(<Plot {...props} />);

props.skipNonBusinessHours = true;
rerender(<Plot {...props} />);

expect(asFragment()).toMatchSnapshot();
});

it('updates data object correctly when XAxis is not set (aka when user switches from timeseries to XY plot)', () => {
const { rerender, asFragment } = render(<Plot {...props} />);

Expand Down
19 changes: 19 additions & 0 deletions src/plotting/plot.component.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import type {
PlotData as PlotlyPlotData,
} from 'plotly.js';
import { useTheme } from '@mui/material';
import type { WorkingHours } from '../settings';

export interface PlotProps {
datasets: PlotDataset[];
Expand All @@ -36,6 +37,8 @@ export interface PlotProps {
leftYAxisLabel?: string;
rightYAxisLabel?: string;
viewReset: boolean;
workingHours: WorkingHours;
skipNonBusinessHours: boolean;
}

const Plot = (props: PlotProps) => {
Expand All @@ -61,6 +64,8 @@ const Plot = (props: PlotProps) => {
leftYAxisLabel,
rightYAxisLabel,
viewReset,
workingHours,
skipNonBusinessHours,
} = props;

const {
Expand Down Expand Up @@ -148,6 +153,17 @@ const Plot = (props: PlotProps) => {
range: [xMin ?? null, xMax ?? null],
minallowed: xMin,
maxallowed: xMax,
...(XAxisScale === 'date' && skipNonBusinessHours
? {
rangebreaks: [
{ pattern: 'day of week', bounds: ['sat', 'mon'] }, // skips from saturday to monday
{
pattern: 'hour',
bounds: [workingHours.end, workingHours.start],
}, // skips from end to start as defined in the config
],
}
: {}),
color: lineColour,
gridcolor: lineColour,
tickfont: { color: fontColour },
Expand Down Expand Up @@ -220,6 +236,9 @@ const Plot = (props: PlotProps) => {
rightYAxisLabel,
viewReset,
themeMode,
skipNonBusinessHours,
workingHours.end,
workingHours.start,
]);

React.useEffect(() => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,14 +30,48 @@ changeXAxis=undefined
</mock-charttypebuttons>
</div>
<div
class="MuiGrid-root MuiGrid-item css-yu75kd-MuiGrid-root"
>
<label
class="MuiFormControlLabel-root MuiFormControlLabel-labelPlacementEnd css-j204z7-MuiFormControlLabel-root"
>
<span
class="MuiSwitch-root MuiSwitch-sizeSmall css-1diaq70-MuiSwitch-root"
>
<span
class="MuiButtonBase-root MuiSwitch-switchBase MuiSwitch-colorPrimary PrivateSwitchBase-root MuiSwitch-switchBase MuiSwitch-colorPrimary css-byenzh-MuiButtonBase-root-MuiSwitch-switchBase"
>
<input
class="PrivateSwitchBase-input MuiSwitch-input css-1m9pwf3"
type="checkbox"
/>
<span
class="MuiSwitch-thumb css-jsexje-MuiSwitch-thumb"
/>
<span
class="MuiTouchRipple-root css-8je8zh-MuiTouchRipple-root"
/>
</span>
<span
class="MuiSwitch-track css-1yjjitx-MuiSwitch-track"
/>
</span>
<span
class="MuiTypography-root MuiTypography-body1 MuiFormControlLabel-label css-ahj2mt-MuiTypography-root"
>
Skip Non-Business Hours
</span>
</label>
</div>
<div
class="MuiGrid-root MuiGrid-item css-13i4rnv-MuiGrid-root"
>
<div
class="MuiPaper-root MuiPaper-outlined MuiPaper-rounded css-9axob7-MuiPaper-root"
>
<p
class="MuiTypography-root MuiTypography-body1 css-ahj2mt-MuiTypography-root"
class="MuiTypography-root MuiTypography-body1 css-d3w48x-MuiTypography-root"
>
X Axis Config
</p>
Expand Down Expand Up @@ -105,7 +139,7 @@ changeXMaximum=undefined
class="MuiPaper-root MuiPaper-outlined MuiPaper-rounded css-ibczwg-MuiPaper-root"
>
<p
class="MuiTypography-root MuiTypography-body1 css-ahj2mt-MuiTypography-root"
class="MuiTypography-root MuiTypography-body1 css-d3w48x-MuiTypography-root"
>
Y Axes Config
</p>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
exports[`x-axis tab > renders correctly with arbitrary x axis 1`] = `
<DocumentFragment>
<div
class="MuiGrid-root MuiGrid-container MuiGrid-spacing-xs-1 css-1w7ngrt-MuiGrid-root"
class="MuiGrid-root MuiGrid-container MuiGrid-spacing-xs-1 css-98dqc1-MuiGrid-root"
>
<div
class="MuiGrid-root MuiGrid-container MuiGrid-item MuiGrid-spacing-xs-1 css-v8g4am-MuiGrid-root"
Expand Down Expand Up @@ -98,7 +98,7 @@ exports[`x-axis tab > renders correctly with arbitrary x axis 1`] = `
class="MuiFormControl-root css-qtsj9i-MuiFormControl-root"
>
<label
class="MuiFormLabel-root MuiFormLabel-colorPrimary css-7dax6m-MuiFormLabel-root"
class="MuiFormLabel-root MuiFormLabel-colorPrimary css-t8wj1j-MuiFormLabel-root"
id="x-scale-group-label"
>
Scale
Expand All @@ -112,7 +112,7 @@ exports[`x-axis tab > renders correctly with arbitrary x axis 1`] = `
class="MuiFormControlLabel-root MuiFormControlLabel-labelPlacementEnd css-j204z7-MuiFormControlLabel-root"
>
<span
class="MuiButtonBase-root MuiRadio-root MuiRadio-colorPrimary PrivateSwitchBase-root MuiRadio-root MuiRadio-colorPrimary Mui-checked MuiRadio-root MuiRadio-colorPrimary css-vqmohf-MuiButtonBase-root-MuiRadio-root"
class="MuiButtonBase-root MuiRadio-root MuiRadio-colorPrimary PrivateSwitchBase-root MuiRadio-root MuiRadio-colorPrimary Mui-checked MuiRadio-root MuiRadio-colorPrimary css-1dt26j0-MuiButtonBase-root-MuiRadio-root"
>
<input
checked=""
Expand Down Expand Up @@ -161,7 +161,7 @@ exports[`x-axis tab > renders correctly with arbitrary x axis 1`] = `
class="MuiFormControlLabel-root MuiFormControlLabel-labelPlacementEnd css-j204z7-MuiFormControlLabel-root"
>
<span
class="MuiButtonBase-root MuiRadio-root MuiRadio-colorPrimary PrivateSwitchBase-root MuiRadio-root MuiRadio-colorPrimary MuiRadio-root MuiRadio-colorPrimary css-vqmohf-MuiButtonBase-root-MuiRadio-root"
class="MuiButtonBase-root MuiRadio-root MuiRadio-colorPrimary PrivateSwitchBase-root MuiRadio-root MuiRadio-colorPrimary MuiRadio-root MuiRadio-colorPrimary css-1dt26j0-MuiButtonBase-root-MuiRadio-root"
>
<input
class="PrivateSwitchBase-input css-1m9pwf3"
Expand Down Expand Up @@ -339,7 +339,7 @@ exports[`x-axis tab > renders correctly with arbitrary x axis 1`] = `
exports[`x-axis tab > renders correctly with timestamp x axis 1`] = `
<DocumentFragment>
<div
class="MuiGrid-root MuiGrid-container MuiGrid-spacing-xs-1 css-1w7ngrt-MuiGrid-root"
class="MuiGrid-root MuiGrid-container MuiGrid-spacing-xs-1 css-98dqc1-MuiGrid-root"
>
<div
class="MuiGrid-root MuiGrid-container MuiGrid-item MuiGrid-spacing-xs-1 css-v8g4am-MuiGrid-root"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
exports[`y-axis tab > renders correctly 1`] = `
<DocumentFragment>
<div
class="MuiGrid-root MuiGrid-container MuiGrid-spacing-xs-1 css-1w7ngrt-MuiGrid-root"
class="MuiGrid-root MuiGrid-container MuiGrid-spacing-xs-1 css-98dqc1-MuiGrid-root"
>
<div
class="MuiGrid-root MuiGrid-item css-13i4rnv-MuiGrid-root"
Expand Down Expand Up @@ -173,7 +173,7 @@ exports[`y-axis tab > renders correctly 1`] = `
class="MuiFormControl-root css-qtsj9i-MuiFormControl-root"
>
<label
class="MuiFormLabel-root MuiFormLabel-colorPrimary css-7dax6m-MuiFormLabel-root"
class="MuiFormLabel-root MuiFormLabel-colorPrimary css-t8wj1j-MuiFormLabel-root"
id="left-y-scale-group-label"
>
Scale
Expand All @@ -187,7 +187,7 @@ exports[`y-axis tab > renders correctly 1`] = `
class="MuiFormControlLabel-root MuiFormControlLabel-labelPlacementEnd css-j204z7-MuiFormControlLabel-root"
>
<span
class="MuiButtonBase-root MuiRadio-root MuiRadio-colorPrimary PrivateSwitchBase-root MuiRadio-root MuiRadio-colorPrimary Mui-checked MuiRadio-root MuiRadio-colorPrimary css-vqmohf-MuiButtonBase-root-MuiRadio-root"
class="MuiButtonBase-root MuiRadio-root MuiRadio-colorPrimary PrivateSwitchBase-root MuiRadio-root MuiRadio-colorPrimary Mui-checked MuiRadio-root MuiRadio-colorPrimary css-1dt26j0-MuiButtonBase-root-MuiRadio-root"
>
<input
checked=""
Expand Down Expand Up @@ -236,7 +236,7 @@ exports[`y-axis tab > renders correctly 1`] = `
class="MuiFormControlLabel-root MuiFormControlLabel-labelPlacementEnd css-j204z7-MuiFormControlLabel-root"
>
<span
class="MuiButtonBase-root MuiRadio-root MuiRadio-colorPrimary PrivateSwitchBase-root MuiRadio-root MuiRadio-colorPrimary MuiRadio-root MuiRadio-colorPrimary css-vqmohf-MuiButtonBase-root-MuiRadio-root"
class="MuiButtonBase-root MuiRadio-root MuiRadio-colorPrimary PrivateSwitchBase-root MuiRadio-root MuiRadio-colorPrimary MuiRadio-root MuiRadio-colorPrimary css-1dt26j0-MuiButtonBase-root-MuiRadio-root"
>
<input
class="PrivateSwitchBase-input css-1m9pwf3"
Expand Down
Loading

0 comments on commit 8029c56

Please sign in to comment.