diff --git a/e2e/tests/helpers.js b/e2e/tests/helpers.js
index 4ab0c40e13..f7bc97e4cf 100644
--- a/e2e/tests/helpers.js
+++ b/e2e/tests/helpers.js
@@ -614,7 +614,7 @@ const switchRegionTreeView = (viewName) => {
Htx.annotationStore.selected.regionStore.setView(viewName);
};
-const serialize = () => window.Htx.annotationStore.selected.serializeAnnotation();
+const serialize = async () => await window.Htx.annotationStore.selected.serializeAnnotation();
const selectText = async ({ selector, rangeStart, rangeEnd }) => {
let [doc, win] = [document, window];
diff --git a/e2e/tests/smart-tools.history.test.js b/e2e/tests/smart-tools.history.test.js
index 928cae864e..3cb0ba8289 100644
--- a/e2e/tests/smart-tools.history.test.js
+++ b/e2e/tests/smart-tools.history.test.js
@@ -22,7 +22,7 @@ function createRectangleConfig(params = {}) {
const IMAGE = 'https://upload.wikimedia.org/wikipedia/commons/thumb/d/df/Html_headers.png/640px-Html_headers.png';
-function getRectangleSuggestions(reg, group) {
+async function getRectangleSuggestions(reg, group) {
const allSuggestions = [{
'original_width': 640,
'original_height': 507,
@@ -451,7 +451,7 @@ function getRectangleSuggestions(reg, group) {
}];
const annotation = window.labelStudio.store.annotationStore.selected;
const ids = group.map(r => r.id);
- const results = annotation.serializeAnnotation().filter((res) => ids.includes(res.id));
+ const results = (await annotation.serializeAnnotation()).filter((res) => ids.includes(res.id));
const suggestions = allSuggestions.filter(predictionResult => {
const targetCenterX = predictionResult.value.x + predictionResult.value.width / 2;
const targetCenterY = predictionResult.value.y + predictionResult.value.height / 2;
@@ -473,6 +473,9 @@ function getRectangleSuggestions(reg, group) {
}
Scenario('Undo regions auto-annotated from predictions', async function({ I, LabelStudio, AtImageView, AtSidebar }) {
+ LabelStudio.setFeatureFlags({
+ fflag_fix_front_dev_1284_auto_detect_undo_281022_short: true,
+ });
I.amOnPage('/');
LabelStudio.init({
config: createRectangleConfig({
@@ -492,9 +495,6 @@ Scenario('Undo regions auto-annotated from predictions', async function({ I, Lab
forceAutoAcceptSuggestions: true,
},
});
- LabelStudio.setFeatureFlags({
- fflag_fix_front_dev_1284_auto_detect_undo_281022_short: true,
- });
AtImageView.waitForImage();
AtSidebar.seeRegions(0);
await AtImageView.lookForStage();
diff --git a/package.json b/package.json
index 7db0eee5f5..2879c9efb1 100644
--- a/package.json
+++ b/package.json
@@ -132,6 +132,8 @@
"@types/react-window": "^1.8.5",
"@types/strman": "^2.0.0",
"@types/wavesurfer.js": "^6.0.0",
+ "@typescript-eslint/eslint-plugin": "^6.18.0",
+ "@typescript-eslint/parser": "^6.18.0",
"@wojtekmaj/enzyme-adapter-react-17": "^0.4.1",
"antd": "^4.3.3",
"autoprefixer": "^10.4.2",
@@ -142,14 +144,16 @@
"chroma-js": "^2.1.1",
"css-loader": "^6.7.3",
"css-minimizer-webpack-plugin": "^3.0.2",
- "d3": "^5.16.0",
"date-fns": "^2.20.1",
"dotenv-defaults": "^2.0.2",
"dotenv-webpack": "^7.0.2",
"emoji-regex": "^7.0.3",
"enzyme": "^3.11.0",
"enzyme-to-json": "^3.5.0",
- "eslint": "^8.28.0",
+ "eslint": "^8.56.0",
+ "eslint-config-airbnb-base": "^15.0.0",
+ "eslint-plugin-import": "^2.29.1",
+ "eslint-plugin-react": "^7.33.2",
"eslint-webpack-plugin": "^3.0.1",
"file-loader": "^6.2.0",
"html-webpack-plugin": "^5.3.1",
@@ -197,7 +201,7 @@
"svg.js": "^2.7.0",
"terser-webpack-plugin": "^5.1.1",
"ts-jest": "^29.0.3",
- "typescript": "^4.2.3",
+ "typescript": "^5.0.4",
"url-loader": "^4.1.1",
"wavesurfer.js": "^6.0.1",
"webpack": "^5.79.0",
diff --git a/public/index.html b/public/index.html
index e49228834c..dafd6a415e 100644
--- a/public/index.html
+++ b/public/index.html
@@ -159,7 +159,7 @@
}
})
ls.on("updateAnnotation", (_, annotation) => {
- console.log(annotation.serializeAnnotation());
+ annotation.serializeAnnotation().then(console.log);
})
ls.on("regionFinishedDrawing", (region, list) => {
console.log("finish drawing", {region, list})
diff --git a/src/components/Debug.js b/src/components/Debug.js
index 9a30070bed..18187104ba 100644
--- a/src/components/Debug.js
+++ b/src/components/Debug.js
@@ -3,9 +3,9 @@ import { Button, Form } from 'antd';
import { observer } from 'mobx-react';
-const toJSON = (annotation) => {
+const toJSON = async (annotation) => {
const id = annotation.pk || annotation.id;
- const result = annotation.serializeAnnotation();
+ const result = await annotation.serializeAnnotation();
const draft = annotation.versions.draft;
const json = { id, result };
@@ -32,22 +32,22 @@ const DebugComponent = ({ store }) => {
if (cs.annotations.length) cs.selectAnnotation(cs.annotations[0].id);
}, []);
- const serializeCurrent = useCallback(() => {
+ const serializeCurrent = useCallback(async () => {
const input = refAnnotations.current;
if (!input) return;
const annotation = store.annotationStore.selected;
- const json = [toJSON(annotation)];
+ const json = await toJSON(annotation);
input.value = JSON.stringify(json, null, 2);
}, []);
- const serializeAll = useCallback(() => {
+ const serializeAll = useCallback(async () => {
const input = refAnnotations.current;
if (!input) return;
const { annotations, predictions } = store.annotationStore;
- const json = [...annotations, ...predictions].map(toJSON);
+ const json = await Promise.all([...annotations, ...predictions].map(toJSON));
input.value = JSON.stringify(json, null, 2);
}, []);
diff --git a/src/components/ImageView/Image.js b/src/components/ImageView/Image.js
index fb0b6a349f..56157413e9 100644
--- a/src/components/ImageView/Image.js
+++ b/src/components/ImageView/Image.js
@@ -30,6 +30,7 @@ export const Image = observer(forwardRef(({
updateImageSize,
usedValue,
size,
+ overlay,
}, ref) => {
const imageSize = useMemo(() => {
return {
@@ -45,6 +46,7 @@ export const Image = observer(forwardRef(({
return (
+ {overlay}
Downloading image
-
+
) : error ? (
@@ -121,6 +123,6 @@ const ImageLoadingError = ({ src, value }) => {
}, [src]);
return (
-
+
);
};
diff --git a/src/components/ImageView/ImageView.js b/src/components/ImageView/ImageView.js
index 08b82bedfe..f4d6db7b49 100644
--- a/src/components/ImageView/ImageView.js
+++ b/src/components/ImageView/ImageView.js
@@ -403,7 +403,7 @@ const Selection = observer(({ item, ...triggeredOnResize }) => {
return (
<>
- { isFF(FF_DBLCLICK_DELAY)
+ {isFF(FF_DBLCLICK_DELAY)
?
:
}
@@ -490,6 +490,22 @@ const Crosshair = memo(forwardRef(({ width, height }, ref) => {
);
}));
+/**
+ * Component that creates an overlay on top
+ * of the image to support Magic Wand tool
+ */
+const CanvasOverlay = observer(({ item }) => {
+ return isFF(FF_DEV_4081) ? (
+