Skip to content

Commit

Permalink
[UI] EVEREST-1647 Restrict selectable hours for PSMDB db with monthly…
Browse files Browse the repository at this point in the history
… schedule (#1009)

* fix: restrict selectable hours for PSMDB database for first day monthly schedule with UTC+ timezone

* fix: typo

* fix: typo

* fix: set selectable minutes when timezone is UTC+X:30

* test: unit test for TimeSelection

* fix: only restrict interval for AM values

* fixes:
- disable unavailable hours instead of removing them from select
- fix logic for TZ > +12
- add tooltip and help icon for selects with disabled options

* fix: change docker images directory

* fix: set time back to first available time when changing am/pm, don't restrict pm hours if am hours are unavailable, remove edit mode condition

* fix: only restrict minutes for first hour available

* fix logic for restricting UTC+12:00

* fix: condition

---------

Co-authored-by: Fábio Silva <[email protected]>
Co-authored-by: Percona Platform Robot <[email protected]>
  • Loading branch information
3 people authored Feb 5, 2025
1 parent 06ea679 commit 98dbc02
Show file tree
Hide file tree
Showing 8 changed files with 301 additions and 18 deletions.
9 changes: 4 additions & 5 deletions .github/workflows/dev-fe-e2e.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,8 @@ jobs:
strategy:
fail-fast: false
matrix:
go-version: [ 1.23.x ]
may-fail: [ false ]
go-version: [1.23.x]
may-fail: [false]
runs-on: ubuntu-latest
steps:
# Setup Go
Expand Down Expand Up @@ -87,7 +87,7 @@ jobs:
cpus: 4
memory: 4000m
addons: registry
insecure-registry: 'localhost:5000'
insecure-registry: "localhost:5000"

- name: Expose local registry
run: |
Expand Down Expand Up @@ -121,8 +121,7 @@ jobs:
id: meta
with:
images: localhost:5000/perconalab/everest
tags:
0.0.0
tags: 0.0.0

- name: Build and Push everest dev image
uses: docker/build-push-action@v6
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,11 @@ export const ScheduleForm = ({
isRequired
/>
<LabeledContent label={Messages.repeats}>
<TimeSelection showInfoAlert errorInfoAlert={errorInfoAlert} />
<TimeSelection
showInfoAlert
errorInfoAlert={errorInfoAlert}
shouldRestrictSelectableHours={dbEngine === DbEngineType.PSMDB}
/>
</LabeledContent>
</>
);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,52 @@
import { Box, MenuItem, Typography } from '@mui/material';
import { Box, Divider, MenuItem, Tooltip, Typography } from '@mui/material';
import { useFormContext } from 'react-hook-form';
import { SelectInput } from '@percona/ui-lib';
import { HOURS_AM_PM, MINUTES } from '../time-selection.constants';
import { AM_PM, HOURS_AM_PM, MINUTES } from '../time-selection.constants';
import { Messages } from '../time-selection.messages';
import { AmPM, TimeSelectionFields } from '../time-selection.types';
import { TimeSelectionFields } from '../time-selection.types';
import { addZeroToSingleDigit } from '../time-selection.utils';
import HelpIcon from '@mui/icons-material/Help';

export const TimeFields = () => {
const showLimitationInfo = () => {
return (
<Box>
<MenuItem
sx={{
cursor: 'text',
userSelect: 'text',
maxHeight: '20px',
paddingLeft: '5px',
}}
>
<HelpIcon sx={{ size: 'small' }} />

<Tooltip
title={Messages.notAvailable}
arrow
placement="right"
sx={{ ml: 1 }}
>
<Typography variant="helperText" color="text.secondary">
{Messages.help}
</Typography>
</Tooltip>
</MenuItem>
<Divider />
</Box>
);
};

export const TimeFields = ({
selectableHours = HOURS_AM_PM,
selectableMinutes = MINUTES,
selectableAmPm = AM_PM,
shouldRestrictTime,
}: {
selectableHours?: number[];
selectableMinutes?: number[];
selectableAmPm?: string[];
shouldRestrictTime: boolean;
}) => {
const { control } = useFormContext();

return (
Expand All @@ -28,8 +68,15 @@ export const TimeFields = () => {
sx: { minWidth: '80px' },
}}
>
{shouldRestrictTime &&
HOURS_AM_PM.length !== selectableHours.length &&
showLimitationInfo()}
{HOURS_AM_PM.map((value) => (
<MenuItem key={value} value={value}>
<MenuItem
key={value}
value={value}
disabled={!selectableHours.includes(value)}
>
{value}
</MenuItem>
))}
Expand All @@ -38,11 +85,18 @@ export const TimeFields = () => {
name={TimeSelectionFields.minute}
control={control}
selectFieldProps={{
sx: { minWidth: '80px' },
sx: { minWidth: '80px', width: 'fit-content', margin: '5px' },
}}
>
{shouldRestrictTime &&
MINUTES.length !== selectableMinutes.length &&
showLimitationInfo()}
{MINUTES.map((value) => (
<MenuItem key={value} value={value}>
<MenuItem
key={value}
value={value}
disabled={!selectableMinutes.includes(value)}
>
{addZeroToSingleDigit(value)}
</MenuItem>
))}
Expand All @@ -54,8 +108,18 @@ export const TimeFields = () => {
sx: { minWidth: '80px' },
}}
>
<MenuItem value={AmPM.AM}>{Messages.am}</MenuItem>
<MenuItem value={AmPM.PM}>{Messages.pm}</MenuItem>
{shouldRestrictTime &&
AM_PM.length !== selectableAmPm.length &&
showLimitationInfo()}
{AM_PM.map((value) => (
<MenuItem
key={value}
value={value}
disabled={!selectableAmPm.includes(value)}
>
{value}
</MenuItem>
))}
</SelectInput>
</Box>
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import {
export const MINUTES = Array.from({ length: 60 }, (_, i) => i);
export const DAYS_MONTH = Array.from({ length: 31 }, (_, i) => i + 1);
export const HOURS_AM_PM = Array.from({ length: 12 }, (_, i) => i + 1);
export const AM_PM = [AmPM.AM, AmPM.PM];

export const TIME_SELECTION_DEFAULTS = {
[TimeSelectionFields.selectedTime]: TimeValue.days,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,9 @@ export const Messages = {
at: 'at',
am: 'AM',
pm: 'PM',
notAvailable:
'Some time slots are not available due to operator limitations.',
help: 'Help',
infoText: (value: string) =>
`Everest will create a backup of your database every ${value}`,
getTimeText: {
Expand Down
108 changes: 108 additions & 0 deletions ui/apps/everest/src/components/time-selection/time-selection.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -127,4 +127,112 @@ describe('TimeSelection', () => {
screen.queryByTestId('select-input-week-day')
).not.toBeInTheDocument();
});

it('should render correctly for monthly values for UTX+X:30 timezone', () => {
vi.stubEnv('TZ', 'Asia/Calcutta');
render(
<TestWrapper>
<FormProviderWrapper>
<TimeSelection shouldRestrictSelectableHours />
</FormProviderWrapper>
</TestWrapper>
);

const selectTimeValue = screen.getByTestId('select-input-selected-time');
expect(selectTimeValue).toBeInTheDocument();

fireEvent.change(selectTimeValue, { target: { value: 'month' } });

expect(selectTimeValue.getAttribute('value')).toBe('month');

expect(screen.getByTestId('select-input-hour')).toHaveAttribute(
'value',
'5'
);
expect(screen.getByTestId('select-input-minute')).toHaveAttribute(
'value',
'30'
);
});

it('should render correctly for UTX+X timezone when monthly is selected', () => {
vi.stubEnv('TZ', 'Europe/Amsterdam');
render(
<TestWrapper>
<FormProviderWrapper>
<TimeSelection shouldRestrictSelectableHours />
</FormProviderWrapper>
</TestWrapper>
);

const selectTimeValue = screen.getByTestId('select-input-selected-time');
expect(selectTimeValue).toBeInTheDocument();

fireEvent.change(selectTimeValue, { target: { value: 'month' } });

expect(selectTimeValue.getAttribute('value')).toBe('month');

expect(screen.getByTestId('select-input-hour')).toHaveAttribute(
'value',
'1'
);
expect(screen.getByTestId('select-input-minute')).toHaveAttribute(
'value',
'0'
);
});

it('should render correctly for UTX-X timezone if monthly is selected ', () => {
vi.stubEnv('TZ', 'America/Los_Angeles');
render(
<TestWrapper>
<FormProviderWrapper>
<TimeSelection shouldRestrictSelectableHours />
</FormProviderWrapper>
</TestWrapper>
);

const selectTimeValue = screen.getByTestId('select-input-selected-time');
expect(selectTimeValue).toBeInTheDocument();

fireEvent.change(selectTimeValue, { target: { value: 'month' } });

expect(selectTimeValue.getAttribute('value')).toBe('month');

expect(screen.getByTestId('select-input-hour')).toHaveAttribute(
'value',
'12'
);
expect(screen.getByTestId('select-input-minute')).toHaveAttribute(
'value',
'0'
);
});

it('should render normally if monthly is selected and selectable hours are not restricted', () => {
vi.stubEnv('TZ', 'Asia/Calcutta');
render(
<TestWrapper>
<FormProviderWrapper>
<TimeSelection shouldRestrictSelectableHours={false} />
</FormProviderWrapper>
</TestWrapper>
);

const selectTimeValue = screen.getByTestId('select-input-selected-time');
expect(selectTimeValue).toBeInTheDocument();

fireEvent.change(selectTimeValue, { target: { value: 'month' } });

expect(selectTimeValue.getAttribute('value')).toBe('month');

expect(screen.getByTestId('select-input-hour')).toHaveAttribute(
'value',
'12'
);
expect(screen.getByTestId('select-input-minute')).toHaveAttribute(
'value',
'0'
);
});
});
Loading

0 comments on commit 98dbc02

Please sign in to comment.