Skip to content

Commit

Permalink
Added a dialog regarding unsaved changes
Browse files Browse the repository at this point in the history
  • Loading branch information
justinnas committed Sep 15, 2024
1 parent 45aa000 commit 0946efb
Show file tree
Hide file tree
Showing 6 changed files with 186 additions and 59 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
import { FileTreeItemContextMenuStyledDialog } from '@/features/editor/components/fileTreeView/fileTreeItem';
import { useStatusContext } from '@/hooks';
import { Close as CloseIcon } from '@mui/icons-material';
import {
Box,
Button,
DialogActions,
DialogContent,
DialogTitle,
Grid,
IconButton,
Typography,
useTheme,
} from '@mui/material';
import { useCallback } from 'react';

interface EditorConfirmLeaveDialogProps {
onConfirm: () => void;
isOpen: boolean;
onClose: () => void;
}

export const EditorConfirmLeave: React.FC<EditorConfirmLeaveDialogProps> = ({ onConfirm, isOpen, onClose }) => {
const { unsavedStateUpdate } = useStatusContext();
const Theme = useTheme();

const handleConfirm = useCallback(() => {
unsavedStateUpdate(false);
onConfirm();
onClose();
}, [onConfirm, onClose, unsavedStateUpdate]);

return (
<FileTreeItemContextMenuStyledDialog open={isOpen} onClose={onClose}>
<Grid container spacing={2} justifyContent='center' alignItems='center'>
<Grid item xs={8}>
<DialogTitle sx={{ color: Theme.palette.primary.main, pl: '1.5rem', pt: '1.5rem', fontWeight: '700' }}>
Unsaved changes
</DialogTitle>
</Grid>
<Grid item xs={4}>
<Box display='flex' justifyContent='flex-end'>
<IconButton
aria-label='close'
onClick={onClose}
sx={{
color: Theme.palette.primary.main,
mt: '0.5rem',
mr: '1.5rem',
}}
>
<CloseIcon />
</IconButton>
</Box>
</Grid>
</Grid>
<DialogContent sx={{ py: 0 }}>
<Typography sx={{ color: Theme.palette.text.primary, fontSize: '1rem', mb: '1rem' }}>
You have unsaved changes. If you continue, your <b>changes will be lost</b>. <br />
Do you wish to continue?
</Typography>
</DialogContent>
<DialogActions>
<Button onClick={onClose}>
<Typography sx={{ fontSize: '1rem', color: Theme.palette.text.secondary }}>Cancel</Typography>
</Button>
<Button
onClick={handleConfirm}
variant='outlined'
sx={{
borderColor: Theme.palette.primary.main,
':hover': { borderColor: Theme.palette.primary.main, bgcolor: Theme.palette.secondary.main },
'& .MuiTouchRipple-root': {
color: Theme.palette.primary.main,
},
}}
>
Continue
</Button>
</DialogActions>
</FileTreeItemContextMenuStyledDialog>
);
};
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { useStatusContext } from '@/hooks';
import { socket } from '@/lib';
import { Events } from '@/types';
import { Done as DoneIcon, Error as ErrorIcon } from '@mui/icons-material';
import { Box, Button, CircularProgress, useTheme } from '@mui/material';
import { alpha, Box, Button, CircularProgress, Typography, useTheme } from '@mui/material';
import {
GridToolbarColumnsButton,
GridToolbarContainer,
Expand Down Expand Up @@ -52,7 +52,7 @@ export const EditorToolbar: React.FC<EditorToolbarProps> = ({ handleSave }) => {
const [saveStatus, setSaveStatus] = useState(true);

const Theme = useTheme();
const { blocked } = useStatusContext();
const { blocked, unsavedStateUpdate, unsaved } = useStatusContext();

useEffect(() => {
const handleWorkspaceFileSaveFeedback = (data: { status: 'success' | 'error' }) => {
Expand All @@ -73,10 +73,17 @@ export const EditorToolbar: React.FC<EditorToolbarProps> = ({ handleSave }) => {
<GridToolbarDensitySelector />
{/* <GridToolbarExport /> */}
<Box sx={{ flexGrow: 1 }} />
{unsaved && (
<Typography sx={{ fontSize: '0.9rem', color: alpha(Theme.palette.text.primary, 0.5), pr: '0.5rem' }}>
Changes not saved
</Typography>
)}

<Button
onClick={() => {
setIsSaving(true);
handleSave();
unsavedStateUpdate(false);
}}
disabled={blocked}
startIcon={
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,6 @@ export const EditorView: React.FC = () => {

const onCellEditStart = () => {
unsavedStateUpdate(true);
console.log(unsaved);
};

const getWorkspaceFile = useCallback(async () => {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
export { EditorColumnMenu } from './editorColumnMenu';
export { EditorColumnMenuAggregationItem } from './editorColumnMenuAggregationItem';
export type { EditorColumnMenuAggregationItemProps } from './editorColumnMenuAggregationItem';
export { EditorConfirmLeave } from './editorConfirmLeave';
export { EditorHeader } from './editorHeader';
export type { EditorHeaderProps } from './editorHeader';
export { EditorToolbar } from './editorToolbar';
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { EditorConfirmLeave } from '@/features/editor/components/editorView';
import { FileTreeItemContextMenu, FileTreeItemLabel } from '@/features/editor/components/fileTreeView/fileTreeItem';
import { useWorkspaceContext } from '@/features/editor/hooks';
import { FileTypes } from '@/features/editor/types';
Expand Down Expand Up @@ -166,6 +167,13 @@ export const FileTreeItem = React.forwardRef(function CustomTreeItem(
setContextMenuPosition({ top: 0, left: 0 });
};

const [isConfirmDialogOpen, setIsConfirmDialogOpen] = useState(false);
const { unsaved } = useStatusContext();
const handleConfirm = () => {
handleClick(item.id, item.label, item.fileType);
setIsConfirmDialogOpen(false);
};

return (
<TreeItem2Provider itemId={itemId}>
<StyledFileTreeItemRoot {...getRootProps(other)}>
Expand All @@ -174,7 +182,11 @@ export const FileTreeItem = React.forwardRef(function CustomTreeItem(
onClick: (event) => {
if (!blocked) {
if (getContentProps().onClick) getContentProps().onClick(event);
handleClick(item.id, item.label, item.fileType);
if (unsaved) {
setIsConfirmDialogOpen(true);
} else {
handleClick(item.id, item.label, item.fileType);
}
}
},

Expand Down Expand Up @@ -204,6 +216,11 @@ export const FileTreeItem = React.forwardRef(function CustomTreeItem(
onClose={handleCloseContextMenu}
/>
{children && <TransitionComponent {...getGroupTransitionProps()} />}
<EditorConfirmLeave
isOpen={isConfirmDialogOpen}
onClose={() => setIsConfirmDialogOpen(false)}
onConfirm={handleConfirm}
/>
</StyledFileTreeItemRoot>
</TreeItem2Provider>
);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
import { EditorConfirmLeave } from '@/features/editor/components/editorView';
import { useWorkspaceContext } from '@/features/editor/hooks';
import { FileModel } from '@/features/editor/types';
import { useStatusContext } from '@/hooks';
import { Close as CloseIcon } from '@mui/icons-material';
import { alpha, Box, IconButton, Typography, useTheme } from '@mui/material';
import { useCallback, useState } from 'react';

/**
* `FilebarGroupItem` is a functional component that represents an individual item in the file bar group.
Expand All @@ -26,68 +28,86 @@ import { alpha, Box, IconButton, Typography, useTheme } from '@mui/material';
export const FilebarGroupItem: React.FC<FileModel> = (file) => {
const Theme = useTheme();
const Workspace = useWorkspaceContext();
const { blocked } = useStatusContext();
const { blocked, unsaved } = useStatusContext();

const { id, label } = file;

const [isConfirmDialogOpen, setIsConfirmDialogOpen] = useState(false);
const handleConfirm = useCallback(() => {
Workspace.fileStateUpdate(file);
Workspace.filesHistoryStateUpdate(file);
setIsConfirmDialogOpen(false);
}, [file, Workspace]);

return (
<Box
id={id}
sx={{
height: '100%',
pl: '1rem',
pr: '0.5rem',
bgcolor: Workspace.file.id === id ? Theme.palette.background.default : Theme.palette.action.selected,
borderRadius: '0rem',
':hover': {
backgroundColor:
Workspace.file.id === id
? Theme.palette.background.default
: blocked
? Theme.palette.action.selected
: alpha(Theme.palette.background.default, 0.5),
},
cursor: blocked ? 'default' : 'pointer',
display: 'flex',
flexDirection: 'row',
alignItems: 'center',
gap: '0.5rem',
}}
onClick={() => {
// Update the workspace to the selected file
if (!blocked) {
Workspace.fileStateUpdate(file);
Workspace.filesHistoryStateUpdate(file);
}
}}
>
<Typography
<>
<Box
id={id}
sx={{
fontSize: 12,
fontWeight: 'bold',
textTransform: 'none',
maxWidth: '10rem',
overflow: 'hidden',
textOverflow: 'ellipsis',
whiteSpace: 'nowrap',
}}
>
{label}
</Typography>
<IconButton
size='small'
disabled={blocked}
onClick={(event) => {
event.stopPropagation();
height: '100%',
pl: '1rem',
pr: '0.5rem',
bgcolor: Workspace.file.id === id ? Theme.palette.background.default : Theme.palette.action.selected,
borderRadius: '0rem',
':hover': {
backgroundColor:
Workspace.file.id === id
? Theme.palette.background.default
: blocked
? Theme.palette.action.selected
: alpha(Theme.palette.background.default, 0.5),
},
cursor: blocked ? 'default' : 'pointer',
display: 'flex',
flexDirection: 'row',
alignItems: 'center',
gap: '0.5rem',
}}
onMouseDown={(event) => {
event.stopPropagation();
// Remove the file from the workspace
Workspace.filesHistoryStateUpdate(undefined, file);
onClick={() => {
// Update the workspace to the selected file
if (!blocked) {
if (unsaved) {
setIsConfirmDialogOpen(true);
} else {
Workspace.fileStateUpdate(file);
Workspace.filesHistoryStateUpdate(file);
}
}
}}
>
<CloseIcon sx={{ fontSize: 12, color: Theme.palette.text.primary }} />
</IconButton>
</Box>
<Typography
sx={{
fontSize: 12,
fontWeight: 'bold',
textTransform: 'none',
maxWidth: '10rem',
overflow: 'hidden',
textOverflow: 'ellipsis',
whiteSpace: 'nowrap',
}}
>
{label}
</Typography>
<IconButton
size='small'
disabled={blocked}
onClick={(event) => {
event.stopPropagation();
}}
onMouseDown={(event) => {
event.stopPropagation();
// Remove the file from the workspace
Workspace.filesHistoryStateUpdate(undefined, file);
}}
>
<CloseIcon sx={{ fontSize: 12, color: Theme.palette.text.primary }} />
</IconButton>
</Box>
<EditorConfirmLeave
isOpen={isConfirmDialogOpen}
onClose={() => setIsConfirmDialogOpen(false)}
onConfirm={handleConfirm}
/>
</>
);
};

0 comments on commit 0946efb

Please sign in to comment.