Skip to content

Commit

Permalink
added shortcuts info
Browse files Browse the repository at this point in the history
  • Loading branch information
sumn2u committed Oct 24, 2024
1 parent 40f71c1 commit dd64b24
Show file tree
Hide file tree
Showing 7 changed files with 151 additions and 2 deletions.
12 changes: 12 additions & 0 deletions client/src/Annotation/index.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ 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 ShortcutsDialog from "../ShortcutsDialog"
import { clear_db, getSettings } from "../utils/get-data-from-server"
import colors from "../colors.js"
import { useTranslation } from "react-i18next"
Expand Down Expand Up @@ -58,6 +59,7 @@ const userReducer = (state, action) => {

export default () => {
const [selectedImageIndex, changeSelectedImageIndex] = useState(0)
const [openDialog, setOpenDialog] = useState(false)
const [open, setOpen] = useState(false)
const { t } = useTranslation()
const [showLabel, setShowLabel] = useState(true)
Expand Down Expand Up @@ -93,6 +95,14 @@ export default () => {
handleClose()
}

const handleOpenDialog = () => {
setOpenDialog(true)
}

const handleCloseDialog = () => {
setOpenDialog(false)
}

const [loading, setLoading] = useState(true) // Add loading state
const onSelectJumpHandle = (selectedImageName) => {
let selectedImage = imageNames.filter((image) => {
Expand Down Expand Up @@ -348,6 +358,7 @@ export default () => {
exitCancel={t("exit_alert_cancel")}
handleExit={handleExit}
/>
<ShortcutsDialog open={openDialog} handleClose={handleCloseDialog} />
<Annotator
taskDescription={
settings.taskDescription ||
Expand All @@ -367,6 +378,7 @@ export default () => {
onExit={(output) => {
handleClickOpen()
}}
onShortcutClick={() => handleOpenDialog()}
settings={settings}
onSelectJump={onSelectJumpHandle}
showTags={true}
Expand Down
6 changes: 5 additions & 1 deletion client/src/Annotator/index.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ export const Annotator = ({
videoTime = 0,
videoName,
onExit,
onShortcutClick,
settings,
keypointDefinitions,
onSelectJump,
Expand Down Expand Up @@ -148,7 +149,7 @@ export const Annotator = ({

const dispatch = useEventCallback(async (action) => {
if (action.type === "HEADER_BUTTON_CLICKED") {
if (["Exit", "Done", "Save", "Complete"].includes(action.buttonName)) {
if (["Exit", "Done", "Save", "Complete", "Shortcuts"].includes(action.buttonName)) {
// save the current data
if (action.buttonName === "Save") {
const result = await preprocessDataBeforeSend(
Expand All @@ -163,6 +164,8 @@ export const Annotator = ({
payload: result,
})
return null
}else if(action.buttonName === "Shortcuts") {
return onShortcutClick()
} else {
return onExit(without(state, "history"))
}
Expand Down Expand Up @@ -219,6 +222,7 @@ export const Annotator = ({
hideSave={hideSave}
allImages={allImages}
onExit={onExit}
onShortcutClick={onShortcutClick}
enabledRegionProps={enabledRegionProps}
onSelectJump={onSelectJump}
saveActiveImage={saveCurrentData}
Expand Down
3 changes: 3 additions & 0 deletions client/src/Localization/translation-de-DE.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ const translationDeDE = {
"btn.previous": "Zurück",
"btn.save": "Speichern",
"btn.settings": "Einstellungen",
"btn.shortcuts": "Verknüpfungen",
"btn.exit": "Beenden",
"btn.clone": "Klonen",
"btn.play": "Abspielen",
Expand Down Expand Up @@ -97,6 +98,8 @@ const translationDeDE = {
"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",
short_key_up: "Nach oben navigieren",
short_key_down: "Nach unten navigieren",
}

export default translationDeDE
3 changes: 3 additions & 0 deletions client/src/Localization/translation-en-EN.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ const translationEnEN = {
"btn.previous": "Prev",
"btn.save": "Save",
"btn.settings": "Settings",
"btn.shortcuts": "Shortcuts",
"btn.exit": "Exit",
"btn.clone": "Clone",
"btn.play": "Play",
Expand Down Expand Up @@ -96,6 +97,8 @@ const translationEnEN = {
"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",
short_key_up: "Navigate Up",
short_key_down: "Navigate Down",
}

export default translationEnEN
6 changes: 5 additions & 1 deletion client/src/MainLayout/index.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ import getHotkeyHelpText from "../utils/get-hotkey-help-text"
import { useKey } from "react-use"
import { useSettings } from "../SettingsProvider"
import { withHotKeys } from "react-hotkeys"
import { Save, ExitToApp } from "@mui/icons-material"
import { Save, ExitToApp, QuestionMark } from "@mui/icons-material"
import capitalize from "lodash/capitalize"
import { useTranslation } from "react-i18next"
import { useSnackbar } from "../SnackbarContext"
Expand All @@ -47,6 +47,7 @@ export const MainLayout = ({
hideHeader,
hideHeaderText,
onExit,
onShortcutClick,
hideClone = true,
hideSettings = false,
hideSave = false,
Expand Down Expand Up @@ -215,6 +216,8 @@ export const MainLayout = ({
const onClickHeaderItem = useEventCallback((item) => {
if (item.name === "Exit") {
onExit()
} else if (item.name === "Shortcuts") {
onShortcutClick()
} else {
dispatch({ type: "HEADER_BUTTON_CLICKED", buttonName: item.name })
}
Expand Down Expand Up @@ -286,6 +289,7 @@ export const MainLayout = ({
},
{ name: "Docs", label: t("btn.docs") },
!hideSettings && { name: "Settings", label: t("btn.settings") },
{ name: "Shortcuts", label: t("btn.shortcuts"), icon: <QuestionMark/> },
{ name: "Exit", label: t("btn.exit"), icon: <ExitToApp /> },
].filter(Boolean)}
onClickHeaderItem={onClickHeaderItem}
Expand Down
51 changes: 51 additions & 0 deletions client/src/ShortcutsDialog/ShortcutsDialog.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
import React from "react"
import { render, screen, fireEvent } from "@testing-library/react"
import "@testing-library/jest-dom"
import ShortcutsDialog from "./index" // Adjust the import based on your file structure
import { useTranslation } from "react-i18next"

// Mock the useTranslation hook
jest.mock("react-i18next", () => ({
useTranslation: () => ({
t: (key) => key, // Simply return the key as the translation
}),
}))

describe("ShortcutsDialog", () => {
const mockHandleClose = jest.fn()

const defaultProps = {
open: true,
handleClose: mockHandleClose,
}

beforeEach(() => {
render(<ShortcutsDialog {...defaultProps} />)
})

afterEach(() => {
jest.clearAllMocks()
})

test("renders all shortcuts with corresponding actions", () => {
const shortcuts = [
{ key: "Ctrl + Shift + B", action: "helptext_boundingbox" },
{ key: "Ctrl + Shift + Z", action: "helptext_zoom" },
{ key: "Ctrl + Shift + P", action: "helptext_polypolygon" },
{ key: "Ctrl + Shift + C", action: "helptext_circle" },
{ key: "↑", action: "short_key_up" },
{ key: "↓", action: "short_key_down" },
]
shortcuts.forEach((shortcut, index) => {
expect(screen.getByTestId(`shortcut-key-${index}`)).toBeInTheDocument()
})
})

test("calls handleClose when close button is clicked", () => {
const closeButton = screen.getByTestId("close-button")
fireEvent.click(closeButton)
expect(mockHandleClose).toHaveBeenCalledTimes(1)
})


})
72 changes: 72 additions & 0 deletions client/src/ShortcutsDialog/index.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
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 DialogTitle from "@mui/material/DialogTitle"
import Box from "@mui/material/Box"
import Typography from "@mui/material/Typography"
import { useTranslation } from "react-i18next"

export const ShortcutsDialog = ({ open, handleClose }) => {
const { t } = useTranslation()

const shortcuts = [
{ key: "Ctrl + Shift + B", action: t("helptext_boundingbox") },
{ key: "Ctrl + Shift + Z", action: t("helptext_zoom") },
{ key: "Ctrl + Shift + P", action: t("helptext_polypolygon") },
{ key: "Ctrl + Shift + C", action: t("helptext_circle") },
{ key: "↑", action: t("short_key_up") }, // Up arrow key for navigation
{ key: "↓", action: t("short_key_down") }, // Down arrow key for navigation
]

return (
<Dialog
open={open}
onClose={handleClose}
aria-labelledby="shortcuts-dialog-title"
aria-describedby="shortcuts-dialog-description"
data-testid="shortcuts-dialog"
fullWidth
maxWidth="sm"
PaperProps={{
style: {
minHeight: "40vh",
maxHeight: "80vh",
padding: "20px",
},
}}
>
<DialogTitle id="shortcuts-dialog-title" data-testid="shortcuts-dialog-title">
{t("Keyboard Shortcuts")}
</DialogTitle>
<DialogContent data-testid="shortcuts-dialog-content">
<Box display="flex" flexDirection="column" gap={2}>
{shortcuts.map((shortcut, index) => (
<Box
key={index}
display="flex"
justifyContent="space-between"
alignItems="center"
px={1}
>
<Typography variant="body1" data-testid={`shortcut-key-${index}`}>
{shortcut.key}
</Typography>
<Typography variant="body2" data-testid={`shortcut-action-${index}`}>
{shortcut.action}
</Typography>
</Box>
))}
</Box>
</DialogContent>
<DialogActions data-testid="shortcuts-dialog-actions">
<Button onClick={handleClose} data-testid="close-button">
{t("Close")}
</Button>
</DialogActions>
</Dialog>
)
}

export default ShortcutsDialog

0 comments on commit dd64b24

Please sign in to comment.