Skip to content

add confirmation box on exit button click #131

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

Merged
merged 1 commit into from
Jul 8, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
43 changes: 43 additions & 0 deletions client/src/AlertDialog/AlertDialog.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import React from 'react';
import { render, fireEvent, screen } from '@testing-library/react';
import '@testing-library/jest-dom';
import AlertDialog from './index';

describe('AlertDialog Component', () => {
const handleClose = jest.fn();
const handleExit = jest.fn();
const title = "Are you sure you want to exit?";
const description = "Do you really want to exit? This action will clear the storage and all data will be lost.";
const exitConfirm = "Agree";
const exitCancel = "Cancel";

beforeEach(() => {
render(
<AlertDialog
open={true}
handleClose={handleClose}
handleExit={handleExit}
title={title}
description={description}
exitConfirm={exitConfirm}
exitCancel={exitCancel}
/>
);
});

test('renders the alert dialog with correct title and description', () => {
expect(screen.getByTestId('alert-dialog')).toBeInTheDocument();
expect(screen.getByTestId('alert-dialog-title')).toHaveTextContent(title);
expect(screen.getByTestId('alert-dialog-description')).toHaveTextContent(description);
});

test('calls handleClose when cancel button is clicked', () => {
fireEvent.click(screen.getByTestId('disagree-button'));
expect(handleClose).toHaveBeenCalledTimes(1);
});

test('calls handleExit when agree button is clicked', () => {
fireEvent.click(screen.getByTestId('agree-button'));
expect(handleExit).toHaveBeenCalledTimes(1);
});
});
38 changes: 38 additions & 0 deletions client/src/AlertDialog/index.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import * as React from 'react';
import Button from '@mui/material/Button';
import Dialog from '@mui/material/Dialog';
import DialogActions from '@mui/material/DialogActions';
import DialogContent from '@mui/material/DialogContent';
import DialogContentText from '@mui/material/DialogContentText';
import DialogTitle from '@mui/material/DialogTitle';

export const AlertDialog = (props) => {
const { open, handleClose, handleExit, title, description, exitConfirm, exitCancel } = props;

return (
<Dialog
open={open}
onClose={handleClose}
aria-labelledby="alert-dialog-title"
aria-describedby="alert-dialog-description"
data-testid="alert-dialog"
>
<DialogTitle id="alert-dialog-title" data-testid="alert-dialog-title">
{title}
</DialogTitle>
<DialogContent data-testid="alert-dialog-content">
<DialogContentText id="alert-dialog-description" data-testid="alert-dialog-description">
{description}
</DialogContentText>
</DialogContent>
<DialogActions data-testid="alert-dialog-actions">
<Button onClick={handleClose} data-testid="disagree-button">{exitCancel}</Button>
<Button onClick={handleExit} autoFocus data-testid="agree-button">
{exitConfirm}
</Button>
</DialogActions>
</Dialog>
);
}

export default AlertDialog;
92 changes: 68 additions & 24 deletions client/src/Annotation/index.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,10 @@ import { useSnackbar } from '../SnackbarContext'
import { getImagesAnnotation } from "../utils/send-data-to-server"
import CircularProgress from '@mui/material/CircularProgress';
import Box from '@mui/material/Box';
import AlertDialog from "../AlertDialog";
import { clear_db } from "../utils/get-data-from-server"
import colors from "../colors.js";
import {useTranslation} from "react-i18next"

const extractRelevantProps = (region) => ({
cls: region.cls,
Expand Down Expand Up @@ -52,6 +55,8 @@ const userReducer = (state, action) => {

export default () => {
const [selectedImageIndex, changeSelectedImageIndex] = useState(0)
const [open, setOpen] = useState(false);
const {t} = useTranslation();
const [showLabel, setShowLabel] = useState(false)
const [isSettingsOpen, setIsSettingsOpen] = useState(false)
const [imageNames, setImageNames] = useState([])
Expand All @@ -71,7 +76,18 @@ export default () => {
}
})


const handleClickOpen = () => {
setOpen(true);
};

const handleClose = () => {
setOpen(false);
};
const handleExit = () => {
logout()
handleClose()
}

const [loading, setLoading] = useState(true); // Add loading state
const onSelectJumpHandle = (selectedImageName) => {

Expand Down Expand Up @@ -181,6 +197,23 @@ export default () => {
const regions = [ {name: "Polygon", value: "create-polygon"}, {name: "Bounding Box", value: "create-box"}, {name: "Point", value: "create-point"}]
return regions.filter(region => region.name === toolName)[0]?.value || "create-polygon"
}

const reloadApp = () => {
settingsConfig.changeSetting('settings', null);
window.location.reload();
}

const logout = async () => {
try {
const response = await clear_db();
showSnackbar(response.message, 'success');
await new Promise(resolve => setTimeout(resolve, 500)); // Wait for 500 milliseconds
} catch (error) {
showSnackbar(error.message, 'error');
}
reloadApp()
};

const preloadConfiguration = () => {
// get last saved configuration
const savedConfiguration = settingsConfig.settings|| {};
Expand Down Expand Up @@ -221,29 +254,40 @@ export default () => {
<CircularProgress />
</Box>
) : (
<Annotator
taskDescription={settings.taskDescription || "Annotate each image according to this _markdown_ specification."}
images={settings.images || []}
enabledTools={getEnabledTools(settings.configuration.regionTypesAllowed) || []}
regionClsList={settings.configuration.labels.map(label => label.id) || []}
selectedImage={selectedImageIndex}
enabledRegionProps={["class", "comment"]}
userReducer={userReducer}
onExit={(output) => {
console.log("Exiting!");
}}
settings={settings}
onSelectJump={onSelectJumpHandle}
showTags={true}
selectedTool={getToolSelectionType(settings.configuration.regions)}
openDocs={() => window.open(config.DOCS_URL, '_blank')}
hideSettings={false}
onShowSettings={() => {
setIsSettingsOpen(!isSettingsOpen);
setShowLabel(false);
}}
selectedImageIndex={selectedImageIndex}
/>
<>
<AlertDialog
open={open}
handleClose={handleClose}
title={t("exit_alert_title")}
description={t("exit_alert_description")}
exitConfirm={t("exit_alert_confirm")}
exitCancel={t("exit_alert_cancel")}
handleExit= {handleExit}
/>
<Annotator
taskDescription={settings.taskDescription || "Annotate each image according to this _markdown_ specification."}
images={settings.images || []}
enabledTools={getEnabledTools(settings.configuration.regionTypesAllowed) || []}
regionClsList={settings.configuration.labels.map(label => label.id) || []}
selectedImage={selectedImageIndex}
enabledRegionProps={["class", "comment"]}
userReducer={userReducer}
onExit={(output) => {
handleClickOpen()
}}
settings={settings}
onSelectJump={onSelectJumpHandle}
showTags={true}
selectedTool={getToolSelectionType(settings.configuration.regions)}
openDocs={() => window.open(config.DOCS_URL, '_blank')}
hideSettings={false}
onShowSettings={() => {
setIsSettingsOpen(!isSettingsOpen);
setShowLabel(false);
}}
selectedImageIndex={selectedImageIndex}
/>
</>
)}
</>
)}
Expand Down
1 change: 1 addition & 0 deletions client/src/Annotator/index.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -207,6 +207,7 @@ export const Annotator = ({
hideSettings={hideSettings}
hideSave={hideSave}
allImages= {allImages}
onExit={onExit}
enabledRegionProps={enabledRegionProps}
onSelectJump={onSelectJump}
saveActiveImage = {saveCurrentData}
Expand Down
6 changes: 5 additions & 1 deletion client/src/Localization/translation-de-DE.js
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,11 @@ const translationDeDE = {
"expand_selection": "Auswahl erweitern",
"collapse_selection": "Auswahl verkleinern",
"error.image_not_found": "Bild nicht gefunden",
"info": "Die Info"
"info": "Die Info",
"exit_alert_title": "Sind Sie sicher, dass Sie beenden möchten?",
"exit_alert_description": "Möchten Sie wirklich beenden? Diese Aktion wird den Speicher löschen und alle Daten werden verloren gehen.",
"exit_alert_cancel": "Abbrechen",
"exit_alert_confirm": "Zustimmen",
};

export default translationDeDE;
4 changes: 4 additions & 0 deletions client/src/Localization/translation-en-EN.js
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,10 @@ const translationEnEN = {
"collapse_selection": "Collapse selection",
"error.image_not_found": "Image not found",
"info": "Info",
"exit_alert_title": "Are you sure you want to exit?",
"exit_alert_description": "Do you really want to exit? This action will clear the storage and all data will be lost.",
"exit_alert_cancel": "Cancel",
"exit_alert_confirm": "Exit",
};

export default translationEnEN;
19 changes: 2 additions & 17 deletions client/src/MainLayout/index.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@ import {withHotKeys} from "react-hotkeys"
import {Save, ExitToApp} from "@mui/icons-material"
import capitalize from "lodash/capitalize"
import { useTranslation } from "react-i18next"
import { clear_db } from "../utils/get-data-from-server"
import { useSnackbar} from "../SnackbarContext"
import ClassDistributionSidebarBox from "../ClassDistributionSidebarBox"

Expand All @@ -45,6 +44,7 @@ export const MainLayout = ({
onRegionClassAdded,
hideHeader,
hideHeaderText,
onExit,
hideClone = true,
hideSettings = false,
hideSave = false,
Expand Down Expand Up @@ -97,21 +97,6 @@ export const MainLayout = ({
}
}, [])

const reloadApp = () => {
settings.changeSetting('settings', null);
window.location.reload();
}

const logout = async () => {
try {
const response = await clear_db();
showSnackbar(response.message, 'success');
await new Promise(resolve => setTimeout(resolve, 500)); // Wait for 500 milliseconds
} catch (error) {
showSnackbar(error.message, 'error');
}
reloadApp()
};

const canvas = (
<ImageCanvas
Expand Down Expand Up @@ -197,7 +182,7 @@ export const MainLayout = ({

const onClickHeaderItem = useEventCallback((item) => {
if(item.name === "Exit"){
logout()
onExit()
} else {
dispatch({type: "HEADER_BUTTON_CLICKED", buttonName: item.name})
}
Expand Down
Loading