Skip to content

Commit

Permalink
show save button if there are regions presents
Browse files Browse the repository at this point in the history
  • Loading branch information
sumn2u committed Jun 8, 2024
1 parent ee5f676 commit f1b739e
Show file tree
Hide file tree
Showing 6 changed files with 93 additions and 53 deletions.
54 changes: 44 additions & 10 deletions client/src/Annotator/index.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import PropTypes from "prop-types"
import noopReducer from "./reducers/noop-reducer.js"
import {useTranslation} from "react-i18next"
import getActiveImage from "./reducers/get-active-image.js"
import { saveActiveImage } from "../utils/send-data-to-server"
import { saveActiveImage, saveData, splitRegionData, getImageData} from "../utils/send-data-to-server"
import { useSnackbar} from "../SnackbarContext/index.jsx"
export const Annotator = ({
images,
Expand Down Expand Up @@ -124,21 +124,55 @@ export const Annotator = ({
showSnackbar(error.message, 'error');
});
}

const dispatch = useEventCallback((action) => {
const preprocessDataBeforeSend = async (output) => {
const selectedImageIndex = output.selectedImage;
let _image = output.images[selectedImageIndex];
let regions = _image['regions'] || [];
let imageData = getImageData(_image);

imageData['regions'] = [];
for (let regionNum = 0; regionNum < regions.length; regionNum++) {
imageData['regions'].push(splitRegionData(regions[regionNum]));
}

try {
const response = await saveData(imageData);
showSnackbar(response.message, 'success');
return imageData['regions'];
} catch (error) {
showSnackbar(error.message, 'error');
return [];
}
};

const dispatch = useEventCallback(async (action) => {
if (action.type === "HEADER_BUTTON_CLICKED") {
if (["Exit", "Done", "Save", "Complete"].includes(action.buttonName)) {
return onExit(without(state, "history"))
// save the current data
if (action.buttonName === "Save") {
const result = await preprocessDataBeforeSend(without(state, "history"));
dispatchToReducer({
type: "SAVE_LAST_REGIONS",
payload: result
});
dispatchToReducer({
type: "ENABLE_DOWNLOAD",
payload: result
});
return null;
} else {
return onExit(without(state, "history"));
}
} else if (action.buttonName === "Next" && onNextImage) {
saveCurrentData(getActiveImage(state).activeImage)
return onNextImage(without(state, "history"))
saveCurrentData(getActiveImage(state).activeImage);
return onNextImage(without(state, "history"));
} else if (action.buttonName === "Prev" && onPrevImage) {
saveCurrentData(getActiveImage(state).activeImage)
return onPrevImage(without(state, "history"))
saveCurrentData(getActiveImage(state).activeImage);
return onPrevImage(without(state, "history"));
}
}
dispatchToReducer(action)
})
dispatchToReducer(action);
});

const onRegionClassAdded = useEventCallback((cls) => {
dispatchToReducer({
Expand Down
70 changes: 36 additions & 34 deletions client/src/DemoSite/index.jsx
Original file line number Diff line number Diff line change
@@ -1,31 +1,50 @@
import Annotator from "../Annotator"
import React, { useEffect, useState } from "react"
import {saveData, splitRegionData, getImageData} from '../utils/send-data-to-server'
import SetupPage from "../SetupPage";
import { useSnackbar } from '../SnackbarContext';
import { useSettings } from "../SettingsProvider";
import {setIn} from "seamless-immutable"

const extractRelevantProps = (region) => ({
cls: region.cls,
comment: region.comment,
id: region.id,
});

const userReducer = (state, action) => {
switch (action.type) {
// case "SELECT_CLASSIFICATION": {
// switch (action.cls) {
// case "One": {
// return setIn(state, ["selectedTool"], "create-box");
// }
// case "Two": {
// return setIn(state, ["selectedTool"], "create-polygon");
// }
// }
// }
case "CLOSE_REGION_EDITOR":
case "DELETE_REGION": {
const { images, selectedImage } = state;
const lastRegions = state.lastRegions || [];
if (selectedImage != null && lastRegions) {
const currentImage = images[selectedImage];
const regions = currentImage ? (currentImage.regions || []) : [];
if (
regions.length !== lastRegions.length ||
!regions.every((region, index) => {
const lastRegion = lastRegions[index] || [];
const currentProps = extractRelevantProps(region);
const lastProps = extractRelevantProps(lastRegion);
return JSON.stringify(currentProps) === JSON.stringify(lastProps);
})
) {
return setIn(state, ["hasNewChange"], true);
} else {
return setIn(state, ["hasNewChange"], false);
}
}
}
case "SAVE_LAST_REGIONS": {
return setIn(state, ["lastRegions"], action.payload);
}
case "ENABLE_DOWNLOAD": {
return setIn(state, ["enabledDownload"], true);
}
}

return state;
};



export default () => {
const { showSnackbar } = useSnackbar();
const [selectedImageIndex, changeSelectedImageIndex] = useState(0)
const [showLabel, setShowLabel] = useState(false)
const [imageNames, setImageNames] = useState([])
Expand All @@ -42,23 +61,6 @@ export default () => {
}
})

const preprocessDataBeforeSend = (output) => {
const selectedImageIndex = output.selectedImage;
let _image = output.images[selectedImageIndex]
let regions = _image['regions'] || []
let imageData = getImageData(_image)

imageData['regions'] = []
for (let regionNum = 0; regionNum < regions.length; regionNum++){
imageData['regions'].push(splitRegionData(regions[regionNum]))
}
saveData(imageData).then(response => {
showSnackbar(response.message, 'success');
})
.catch(error => {
showSnackbar(error.message, 'error');
});
}

const [loading, setLoading] = useState(true); // Add loading state
const onSelectJumpHandle = (selectedImageName) => {
Expand Down Expand Up @@ -144,7 +146,7 @@ export default () => {
enabledRegionProps= {["class", "comment"]}
userReducer= {userReducer}
onExit={(output) => {
preprocessDataBeforeSend(output)
console.log("Exiting!")
}}
settings={settings}
onSelectJump={onSelectJumpHandle}
Expand Down
5 changes: 3 additions & 2 deletions client/src/MainLayout/index.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -224,17 +224,18 @@ export const MainLayout = ({
) : null,
].filter(Boolean)}
headerItems={[
{ name: "Download", label:t("btn.download"), disabled: !state.enabledDownload, hasInnerMenu: true},
!hidePrev && {name: "Prev", label: t("btn.previous"), disabled: disabledNextAndPrev},
!hideNext && {name: "Next", label: t("btn.next"), disabled: disabledNextAndPrev},
state.annotationType !== "video"
? null
: !state.videoPlaying
? {name: "Play", label: t("btn.play")}
: {name: "Pause", label: t("btn.pause")},
!hideClone &&
!hideClone && state.hasNewChange &&
!nextImageHasRegions &&
activeImage.regions && {name: "Clone", label: t("btn.clone")},
!hideSave && {name: "Save", label:t("btn.save"), icon: <Save />},
!hideSave && {name: "Save", label:t("btn.save"), disabled: !state.hasNewChange, icon: <Save />},
!hideSettings && {name: "Settings", label: t("btn.settings")},
{name: "Exit", label:t("btn.exit"), icon: <ExitToApp />}
].filter(Boolean)}
Expand Down
4 changes: 2 additions & 2 deletions client/src/SetupPage/index.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,7 @@ export const SetupPage = ({setConfiguration, settings, setShowLabel}) => {
{settings.taskChoice === "image_classification" && (
<>
<ConfigureImageClassification config={settings.configuration} onChange={updateConfiguration} />
<Box display="flex" justifyContent="end">
<Box display="flex" justifyContent="end" paddingBottom="6rem">
<Button variant="contained" disabled={!hasConfig} onClick={() => setTab("image")} disableElevation>
{t("btn.next")}
</Button>
Expand All @@ -136,7 +136,7 @@ export const SetupPage = ({setConfiguration, settings, setShowLabel}) => {
{settings.taskChoice === "image_segmentation" && (
<>
<ConfigureImageSegmentation config={settings.configuration} onChange={updateConfiguration} />
<Box display="flex" justifyContent="end">
<Box display="flex" justifyContent="end" paddingBottom="6rem">
<Button variant="contained" disabled={!hasConfig} onClick={() => setTab("image")} disableElevation>
{t("btn.next")}
</Button>
Expand Down
3 changes: 2 additions & 1 deletion client/src/workspace/DownloadButton/index.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import { hexToRgbTuple } from "../../utils/color-utils.js";
import HeaderButton from "../HeaderButton/index.jsx";
import { useTranslation } from "react-i18next"

const DownloadButton = ({selectedImageName, classList, hideHeaderText}) => {
const DownloadButton = ({selectedImageName, classList, hideHeaderText, disabled}) => {
const [anchorEl, setAnchorEl] = useState(null);
const { showSnackbar } = useSnackbar();
const {t} = useTranslation();
Expand Down Expand Up @@ -80,6 +80,7 @@ const DownloadButton = ({selectedImageName, classList, hideHeaderText}) => {
name={"Download"}
label={t("btn.download")}
onClick={handleClick}
disabled={disabled}
icon={<DownloadIcon />}
/>
<Menu
Expand Down
10 changes: 6 additions & 4 deletions client/src/workspace/Header/index.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -33,18 +33,20 @@ export const Header = ({
}) => {

const{ t } = useTranslation()

const downloadMenu = items.find((item) => item.name === "Download")

return (
<ThemeProvider theme={theme}>
<Container>
<BrandText flexGrow={1}>
{t("labname")}
</BrandText>
<Box flexGrow={1}>{leftSideContent}</Box>
<DownloadButton selectedImageName={selectedImageName} classList={classList} hideHeaderText={hideHeaderText}
onDownload={onClickItem}
{downloadMenu && <DownloadButton selectedImageName={selectedImageName} classList={classList} hideHeaderText={hideHeaderText}
onDownload={onClickItem} disabled={downloadMenu.disabled}
/>
{items.map((item) => (
}
{items.filter(item => item.name !== "Download").map((item) => (
<HeaderButton
key={item.name}
hideText={hideHeaderText}
Expand Down

0 comments on commit f1b739e

Please sign in to comment.