Skip to content

Commit b904c53

Browse files
committed
AXON-762: added MUI Snackbar
1 parent 2148a2c commit b904c53

File tree

4 files changed

+128
-1
lines changed

4 files changed

+128
-1
lines changed

src/react/atlascode/startwork/v3/StartWorkPageV3.tsx

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,13 @@ import { RepoData } from '../../../../lib/ipc/toUI/startWork';
88
import { Branch } from '../../../../typings/git';
99
import { AtlascodeErrorBoundary } from '../../common/ErrorBoundary';
1010
import { StartWorkControllerContext, useStartWorkController } from '../startWorkController';
11-
import { CreateBranchSection, SuccessAlert, TaskInfoSection, UpdateStatusSection } from './components';
11+
import {
12+
CreateBranchSection,
13+
SnackbarNotification,
14+
SuccessAlert,
15+
TaskInfoSection,
16+
UpdateStatusSection,
17+
} from './components';
1218
import { generateBranchName, getDefaultSourceBranch } from './utils/branchUtils';
1319

1420
const StartWorkPageV3: React.FunctionComponent = () => {
@@ -31,6 +37,7 @@ const StartWorkPageV3: React.FunctionComponent = () => {
3137
branch?: string;
3238
upstream?: string;
3339
}>({});
40+
const [snackbarOpen, setSnackbarOpen] = useState(false);
3441

3542
// Initialize form with default values
3643
useEffect(() => {
@@ -101,6 +108,10 @@ const StartWorkPageV3: React.FunctionComponent = () => {
101108
setBranchSetupEnabled(enabled);
102109
}, []);
103110

111+
const handleSnackbarClose = useCallback(() => {
112+
setSnackbarOpen(false);
113+
}, []);
114+
104115
const handleCreateBranch = useCallback(async () => {
105116
setSubmitState('submitting');
106117

@@ -127,6 +138,7 @@ const StartWorkPageV3: React.FunctionComponent = () => {
127138

128139
setSubmitResponse(response);
129140
setSubmitState('submit-success');
141+
setSnackbarOpen(true);
130142
} catch (error) {
131143
console.error('Error creating branch:', error);
132144
setSubmitState('initial');
@@ -222,6 +234,16 @@ const StartWorkPageV3: React.FunctionComponent = () => {
222234
</Button>
223235
)}
224236
</Box>
237+
238+
{submitState === 'submit-success' && (
239+
<SnackbarNotification
240+
open={snackbarOpen}
241+
onClose={handleSnackbarClose}
242+
title="Success!"
243+
message="See details at the top of this page"
244+
severity="success"
245+
/>
246+
)}
225247
</AtlascodeErrorBoundary>
226248
</StartWorkControllerContext.Provider>
227249
);
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
import { fireEvent, render, screen } from '@testing-library/react';
2+
import React from 'react';
3+
4+
import { SnackbarNotification } from './SnackbarNotification';
5+
6+
describe('SnackbarNotification', () => {
7+
const mockOnClose = jest.fn();
8+
9+
beforeEach(() => {
10+
jest.clearAllMocks();
11+
});
12+
13+
it('should render when open is true', () => {
14+
render(<SnackbarNotification open={true} onClose={mockOnClose} message="Test message" title="Test title" />);
15+
16+
expect(screen.getByText('Test title')).toBeTruthy();
17+
expect(screen.getByText('Test message')).toBeTruthy();
18+
});
19+
20+
it('should not render when open is false', () => {
21+
render(<SnackbarNotification open={false} onClose={mockOnClose} message="Test message" title="Test title" />);
22+
23+
expect(screen.queryByText('Test title')).toBeNull();
24+
expect(screen.queryByText('Test message')).toBeNull();
25+
});
26+
27+
it('should call onClose when close button is clicked', () => {
28+
render(<SnackbarNotification open={true} onClose={mockOnClose} message="Test message" title="Test title" />);
29+
30+
const closeButton = screen.getByLabelText('close');
31+
fireEvent.click(closeButton);
32+
33+
expect(mockOnClose).toHaveBeenCalledTimes(1);
34+
});
35+
36+
it('should render without title when title is not provided', () => {
37+
render(<SnackbarNotification open={true} onClose={mockOnClose} message="Test message" />);
38+
39+
expect(screen.queryByText('Test title')).toBeNull();
40+
expect(screen.getByText('Test message')).toBeTruthy();
41+
});
42+
43+
it('should render with default severity when not provided', () => {
44+
render(<SnackbarNotification open={true} onClose={mockOnClose} message="Test message" />);
45+
46+
const alert = screen.getByRole('alert');
47+
expect(alert.className).toContain('MuiAlert-standardSuccess');
48+
});
49+
50+
it('should render with custom severity when provided', () => {
51+
render(<SnackbarNotification open={true} onClose={mockOnClose} message="Test message" severity="error" />);
52+
53+
const alert = screen.getByRole('alert');
54+
expect(alert.className).toContain('MuiAlert-standardError');
55+
});
56+
});
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
import { IconButton, Snackbar } from '@material-ui/core';
2+
import CloseIcon from '@material-ui/icons/Close';
3+
import { Alert, AlertTitle } from '@material-ui/lab';
4+
import React, { useCallback } from 'react';
5+
6+
interface SnackbarNotificationProps {
7+
open: boolean;
8+
onClose: () => void;
9+
message: string;
10+
title?: string;
11+
severity?: 'success' | 'error' | 'warning' | 'info';
12+
autoHideDuration?: number;
13+
}
14+
15+
export const SnackbarNotification: React.FC<SnackbarNotificationProps> = ({
16+
open,
17+
onClose,
18+
message,
19+
title,
20+
severity = 'success',
21+
autoHideDuration = 6000,
22+
}) => {
23+
const handleClose = useCallback(() => {
24+
onClose();
25+
}, [onClose]);
26+
27+
return (
28+
<Snackbar
29+
open={open}
30+
onClose={handleClose}
31+
autoHideDuration={autoHideDuration}
32+
anchorOrigin={{ vertical: 'bottom', horizontal: 'left' }}
33+
>
34+
<Alert
35+
variant="standard"
36+
severity={severity}
37+
action={
38+
<IconButton aria-label="close" color="inherit" size="small" onClick={handleClose}>
39+
<CloseIcon fontSize="inherit" />
40+
</IconButton>
41+
}
42+
>
43+
{title && <AlertTitle>{title}</AlertTitle>}
44+
<p>{message}</p>
45+
</Alert>
46+
</Snackbar>
47+
);
48+
};

src/react/atlascode/startwork/v3/components/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ export { CreateBranchSection } from './CreateBranchSection';
22
export { TaskInfoSection } from './TaskInfoSection';
33
export { UpdateStatusSection } from './UpdateStatusSection';
44
export { SuccessAlert } from './SuccessAlert';
5+
export { SnackbarNotification } from './SnackbarNotification';
56
export { RepositorySelector } from './RepositorySelector';
67
export { BranchPrefixSelector } from './BranchPrefixSelector';
78
export { LocalBranchInput } from './LocalBranchInput';

0 commit comments

Comments
 (0)