Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[UI] EVEREST-1647 Restrict selectable hours for PSMDB db with monthly schedule #1009

Open
wants to merge 30 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
4c2f4ac
fix: restrict selectable hours for PSMDB database for first day month…
dianabirs Jan 15, 2025
173efd0
Merge branch 'main' into EVEREST-1647-ui-monthly-schedule-creates-an-…
dianabirs Jan 15, 2025
6354d2b
Merge branch 'main' into EVEREST-1647-ui-monthly-schedule-creates-an-…
dianabirs Jan 16, 2025
43b6f86
Merge branch 'main' into EVEREST-1647-ui-monthly-schedule-creates-an-…
dianabirs Jan 17, 2025
00ced55
Merge branch 'main' into EVEREST-1647-ui-monthly-schedule-creates-an-…
fabio-silva Jan 19, 2025
9f15fa8
Merge branch 'main' into EVEREST-1647-ui-monthly-schedule-creates-an-…
dianabirs Jan 20, 2025
cb3e98c
fix: typo
dianabirs Jan 20, 2025
c29db36
fix: typo
dianabirs Jan 20, 2025
19f676f
fix: set selectable minutes when timezone is UTC+X:30
dianabirs Jan 21, 2025
9542b66
test: unit test for TimeSelection
dianabirs Jan 21, 2025
2282cbf
Merge branch 'main' into EVEREST-1647-ui-monthly-schedule-creates-an-…
dianabirs Jan 21, 2025
a72a3e3
Merge branch 'main' into EVEREST-1647-ui-monthly-schedule-creates-an-…
dianabirs Jan 22, 2025
f4ed087
Merge branch 'main' into EVEREST-1647-ui-monthly-schedule-creates-an-…
dianabirs Jan 23, 2025
ffad493
Merge branch 'main' into EVEREST-1647-ui-monthly-schedule-creates-an-…
percona-robot Jan 23, 2025
c84a310
Merge branch 'main' into EVEREST-1647-ui-monthly-schedule-creates-an-…
percona-robot Jan 23, 2025
34fef9a
Merge branch 'main' into EVEREST-1647-ui-monthly-schedule-creates-an-…
percona-robot Jan 23, 2025
6c2880a
Merge branch 'main' into EVEREST-1647-ui-monthly-schedule-creates-an-…
percona-robot Jan 23, 2025
9879e5a
Merge branch 'main' into EVEREST-1647-ui-monthly-schedule-creates-an-…
percona-robot Jan 23, 2025
78c06b9
Merge branch 'main' into EVEREST-1647-ui-monthly-schedule-creates-an-…
percona-robot Jan 23, 2025
9eee5d1
Merge branch 'main' into EVEREST-1647-ui-monthly-schedule-creates-an-…
percona-robot Jan 23, 2025
f1877b2
Merge branch 'main' into EVEREST-1647-ui-monthly-schedule-creates-an-…
percona-robot Jan 23, 2025
1068d52
Merge branch 'main' into EVEREST-1647-ui-monthly-schedule-creates-an-…
percona-robot Jan 23, 2025
2caa998
Merge branch 'main' into EVEREST-1647-ui-monthly-schedule-creates-an-…
percona-robot Jan 24, 2025
5bed5c9
Merge branch 'main' into EVEREST-1647-ui-monthly-schedule-creates-an-…
percona-robot Jan 27, 2025
69aec2f
Merge branch 'main' into EVEREST-1647-ui-monthly-schedule-creates-an-…
percona-robot Jan 28, 2025
7028344
fix: only restrict interval for AM values
dianabirs Jan 28, 2025
62e1980
fixes:
dianabirs Jan 30, 2025
26c53f4
Merge branch 'main' into EVEREST-1647-ui-monthly-schedule-creates-an-…
percona-robot Jan 31, 2025
3f7b2d5
Merge branch 'main' into EVEREST-1647-ui-monthly-schedule-creates-an-…
percona-robot Jan 31, 2025
66b7935
fix: change docker images directory
dianabirs Jan 31, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions .github/workflows/dev-fe-e2e.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,13 @@ jobs:
e2e:
runs-on: ubuntu-latest
steps:
- name: Switch docker-daemon data directory to /mnt
run: |
sudo systemctl stop docker
echo '{ "exec-opts": ["native.cgroupdriver=cgroupfs"], "cgroup-parent": "/actions_job", "data-root": "/mnt/docker-data" }' | sudo tee /etc/docker/daemon.json
sudo mkdir /mnt/docker-data
sudo systemctl start docker

- uses: actions/checkout@v4
with:
lfs: true
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@
useEffect(() => {
// This allowed us to get an error from zod .superRefine to avoid duplication of checking the schedule with the same time
trigger();
}, [amPm, hour, minute, onDay, weekDay, selectedTime]);

Check warning on line 62 in ui/apps/everest/src/components/schedule-form-dialog/schedule-form-wrapper/schedule-form-wrapper.tsx

View workflow job for this annotation

GitHub Actions / CI_checks (lint)

React Hook useEffect has a missing dependency: 'trigger'. Either include it or remove the dependency array

useEffect(() => {
if (mode === 'edit' && setSelectedScheduleName) {
Expand All @@ -84,6 +84,7 @@
autoFillLocation={mode === 'new'}
disableNameEdit={mode === 'edit'}
schedules={schedules}
editMode={mode === 'edit'}
/>
);
};
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ export const ScheduleForm = ({
schedules,
showTypeRadio,
disableNameEdit = false,
editMode,
}: ScheduleFormProps) => {
const {
formState: { errors },
Expand Down Expand Up @@ -111,7 +112,12 @@ export const ScheduleForm = ({
isRequired
/>
<LabeledContent label={Messages.repeats}>
<TimeSelection showInfoAlert errorInfoAlert={errorInfoAlert} />
<TimeSelection
showInfoAlert
errorInfoAlert={errorInfoAlert}
shouldRestrictSelectableHours={dbEngine === DbEngineType.PSMDB}
editMode={editMode}
/>
</LabeledContent>
</>
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ export type ScheduleFormProps = {
schedules: Schedule[];
showTypeRadio: boolean;
disableNameEdit?: boolean;
editMode: boolean;
};

export const ScheduleFormFields = { ...ScheduleForm, ...TimeSelectionFields };
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
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
Loading