Skip to content
This repository was archived by the owner on Apr 18, 2024. It is now read-only.
Open
Show file tree
Hide file tree
Changes from 22 commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
d2330f7
Fix magic wand in MIG scenario with image preloading
nick-skriabin Apr 19, 2023
cf94623
Fix indentation
nick-skriabin Apr 19, 2023
40c919e
Make serializeAnnotation and BrushRegion#serialize async
nick-skriabin Apr 21, 2023
8b9dcef
Adjust async serialization usages
nick-skriabin Apr 24, 2023
250834f
Merge branch 'master' into fb-lsdv-4864/magic-wand-mig
nick-skriabin Apr 24, 2023
99da5d3
Merge branch 'master' into fb-lsdv-4864/magic-wand-mig
nick-skriabin Apr 24, 2023
8b8c2a9
Fix serializeAnnotation usage
nick-skriabin Apr 26, 2023
33d0e01
Merge branch 'master' into fb-lsdv-4864/magic-wand-mig
nick-skriabin May 3, 2023
e791266
Merge branch 'master' into fb-lsdv-4864/magic-wand-mig
nick-skriabin May 4, 2023
e08a516
Update yarn.lock
nick-skriabin May 4, 2023
e87b4de
Fix image loading
nick-skriabin May 4, 2023
9695b10
Fix async draft submission
nick-skriabin May 5, 2023
2abb1d9
Merge branch 'master' into fb-lsdv-4864/magic-wand-mig
nick-skriabin Jan 8, 2024
efb7311
fix eslint issues
nick-skriabin Jan 8, 2024
283e0a7
Merge branch 'master' into fb-lsdv-4864/magic-wand-mig
nick-skriabin Jan 9, 2024
2ee83ba
Fix tests
nick-skriabin Jan 9, 2024
7c85d16
Merge branch 'master' into fb-lsdv-4864/magic-wand-mig
nick-skriabin Jan 10, 2024
9056771
Update yarn.lock
nick-skriabin Jan 10, 2024
ea97df2
Fix hotkey resolution in tests
nick-skriabin Jan 10, 2024
4303de2
async -> flow
nick-skriabin Jan 10, 2024
ecc46ed
Cleanup formatting
nick-skriabin Jan 12, 2024
c602e6a
Remove traces
nick-skriabin Jan 12, 2024
b88252d
Cleanup formatting
nick-skriabin Jan 12, 2024
3fadf05
Remove unused
nick-skriabin Jan 12, 2024
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
2 changes: 1 addition & 1 deletion e2e/tests/helpers.js
Original file line number Diff line number Diff line change
Expand Up @@ -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];
Expand Down
10 changes: 5 additions & 5 deletions e2e/tests/smart-tools.history.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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;
Expand All @@ -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({
Expand All @@ -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();
Expand Down
10 changes: 7 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand All @@ -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",
Expand Down Expand Up @@ -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",
Expand Down
2 changes: 1 addition & 1 deletion public/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -159,7 +159,7 @@
}
})
ls.on("updateAnnotation", (_, annotation) => {
console.log(annotation.serializeAnnotation());
annotation.serializeAnnotation().then(r => console.log(r));
})
ls.on("regionFinishedDrawing", (region, list) => {
console.log("finish drawing", {region, list})
Expand Down
12 changes: 6 additions & 6 deletions src/components/Debug.js
Original file line number Diff line number Diff line change
Expand Up @@ -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 };

Expand All @@ -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);
}, []);
Expand Down
6 changes: 4 additions & 2 deletions src/components/ImageView/Image.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ export const Image = observer(forwardRef(({
updateImageSize,
usedValue,
size,
overlay,
}, ref) => {
const imageSize = useMemo(() => {
return {
Expand All @@ -45,6 +46,7 @@ export const Image = observer(forwardRef(({

return (
<Block name="image" style={imageSize}>
{overlay}
<ImageProgress
downloading={imageEntity.downloading}
progress={imageEntity.progress}
Expand Down Expand Up @@ -76,7 +78,7 @@ const ImageProgress = observer(({
return downloading ? (
<Block name="image-progress">
<Elem name="message">Downloading image</Elem>
<Elem tag="progress" name="bar" value={progress} min="0" max={1} step={0.0001}/>
<Elem tag="progress" name="bar" value={progress} min="0" max={1} step={0.0001} />
</Block>
) : error ? (
<ImageLoadingError src={src} value={usedValue} />
Expand Down Expand Up @@ -121,6 +123,6 @@ const ImageLoadingError = ({ src, value }) => {
}, [src]);

return (
<ErrorMessage error={error}/>
<ErrorMessage error={error} />
);
};
37 changes: 21 additions & 16 deletions src/components/ImageView/ImageView.js
Original file line number Diff line number Diff line change
Expand Up @@ -403,7 +403,7 @@ const Selection = observer(({ item, ...triggeredOnResize }) => {

return (
<>
{ isFF(FF_DBLCLICK_DELAY)
{isFF(FF_DBLCLICK_DELAY)
? <Layer name="selection-regions-layer" />
: <SelectedRegions item={item} selectedRegions={item.selectedRegions} {...triggeredOnResize} />
}
Expand Down Expand Up @@ -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) ? (
<canvas
className={styles.overlay}
ref={ref => {
item.setOverlayRef(ref);
}}
style={item.imageTransform}
/>
) : null;
});

export default observer(
class ImageView extends Component {
// stored position of canvas before creating region
Expand Down Expand Up @@ -1001,6 +1017,7 @@ export default observer(
imageTransform={item.imageTransform}
updateImageSize={item.updateImageSize}
size={item.canvasSize}
overlay={<CanvasOverlay item={item} />}
/>
) : (
<div
Expand All @@ -1026,15 +1043,7 @@ export default observer(
crossOrigin={item.imageCrossOrigin}
alt="LS"
/>
{isFF(FF_DEV_4081) ? (
<canvas
className={styles.overlay}
ref={ref => {
item.setOverlayRef(ref);
}}
style={item.imageTransform}
/>
) : null}
<CanvasOverlay item={item} />
</div>
)}
{/* @todo this is dirty hack; rewrite to proper async waiting for data to load */}
Expand Down Expand Up @@ -1141,12 +1150,8 @@ const EntireStage = observer(({

return (
<Stage
ref={ref => {
item.setStageRef(ref);
}}
className={[styles['image-element'],
...imagePositionClassnames,
].join(' ')}
ref={ref => item.setStageRef(ref)}
className={[styles['image-element'], ...imagePositionClassnames].join(' ')}
width={size.width}
height={size.height}
scaleX={item.zoomScale}
Expand Down
4 changes: 2 additions & 2 deletions src/regions/BrushRegion.js
Original file line number Diff line number Diff line change
Expand Up @@ -419,7 +419,7 @@ const Model = types
* @param {boolean} [options.fast] Saving only touches, without RLE
* @return {BrushRegionResult}
*/
serialize(options) {
async serialize(options) {
const object = self.object;
const value = { format: 'rle' };

Expand All @@ -429,7 +429,7 @@ const Model = types
if (self.touches.length) value.touches = self.touches;
if (self.maskDataURL) value.maskDataURL = self.maskDataURL;
} else {
const rle = Canvas.Region2RLE(self, object);
const rle = await Canvas.Region2RLE(self, object);

if (!rle || !rle.length) return null;

Expand Down
4 changes: 2 additions & 2 deletions src/regions/Result.js
Original file line number Diff line number Diff line change
Expand Up @@ -270,11 +270,11 @@ const Result = types
// label, becuase it takes color from the label
updateAppearenceFromState() { },

serialize(options) {
async serialize(options) {
const sn = getSnapshot(self);
const { type, score, value, meta } = sn;
const { valueType } = self.from_name;
const data = self.area ? self.area.serialize(options) : {};
const data = self.area ? await self.area.serialize(options) : {};
// cut off annotation id
const id = self.area?.cleanId;
const from_name = Tree.cleanUpId(sn.from_name);
Expand Down
33 changes: 16 additions & 17 deletions src/stores/Annotation/Annotation.js
Original file line number Diff line number Diff line change
Expand Up @@ -202,7 +202,7 @@ export const Annotation = types
return self.results
.map(r => r.serialize())
.filter(Boolean)
.concat(self.relationStore.serialize());
.concat(self.relationStore.serializeAnnotation());
},

get serializedSelection() {
Expand Down Expand Up @@ -651,7 +651,7 @@ export const Annotation = types
self.startAutosave();
},

startAutosave: flow(function *() {
startAutosave: flow(function* () {
if (!getEnv(self).events.hasEvent('submitDraft')) return;
// view all must never trigger autosave
if (self.isReadOnly()) return;
Expand Down Expand Up @@ -681,13 +681,13 @@ export const Annotation = types
onSnapshot(self.areas, self.autosave);
}),

async saveDraft(params) {
saveDraft: flow(function* (params) {
// There is no draft to save as it was already saved as an annotation
if (self.submissionStarted) return;
// if this is now a history item or prediction don't save it
if (!self.editable) return;

const result = self.serializeAnnotation({ fast: true });
const result = yield self.serializeAnnotation({ fast: true });
// if this is new annotation and no regions added yet

if (!isFF(FF_LSDV_3009) && !self.pk && !result.length) return;
Expand All @@ -700,7 +700,7 @@ export const Annotation = types

return res;
});
},
}),

submissionInProgress() {
self.submissionStarted = Date.now();
Expand All @@ -710,14 +710,14 @@ export const Annotation = types
if (self.autosave) self.autosave.flush();
},

async saveDraftImmediatelyWithResults(params) {
saveDraftImmediatelyWithResults: flow(function *(params) {
// There is no draft to save as it was already saved as an annotation
if (self.submissionStarted || self.isDraftSaving) return {};
self.setDraftSaving(true);
const res = await self.saveDraft(params);
const res = yield self.saveDraft(params);

return res;
},
}),

pauseAutosave() {
if (!self.autosave) return;
Expand Down Expand Up @@ -934,20 +934,19 @@ export const Annotation = types
return self.regionStore.regions.slice(prevSize);
},

serializeAnnotation(options) {
// return self.serialized;

serializeAnnotation: flow(function *(options) {
document.body.style.cursor = 'wait';

const result = self.results
.map(r => r.serialize(options))
const result = (yield Promise.all(
self.results.map(r => r.serialize(options)))
)
.filter(Boolean)
.concat(self.relationStore.serialize(options));

document.body.style.cursor = 'default';

return result;
},
}),

// Some annotations may be created with wrong assumptions
// And this problems are fixable, so better to fix them on start
Expand Down Expand Up @@ -1033,7 +1032,7 @@ export const Annotation = types
if (tagNames.has(obj.from_name) && tagNames.has(obj.to_name)) {
res.push(obj);
}

// Insert image dimensions from result
(() => {
if (!isDefined(obj.original_width)) return;
Expand All @@ -1043,7 +1042,7 @@ export const Annotation = types

if (tag.type !== 'image') return;

const imageEntity = tag.findImageEntity(obj.item_index ?? 0);
const imageEntity = tag.findImageEntity(obj.item_index ?? 0);

if (!imageEntity) return;

Expand Down Expand Up @@ -1346,7 +1345,7 @@ export const Annotation = types
area.setValue(state);
});
self.suggestions.delete(id);

},

rejectSuggestion(id) {
Expand Down
Loading