Skip to content

fix: LEAP-1919: update origin on editing classifications results #7312

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 9 commits into from
Apr 9, 2025
Merged
6 changes: 5 additions & 1 deletion web/libs/editor/src/mixins/Regions.js
Original file line number Diff line number Diff line change
Expand Up @@ -283,10 +283,14 @@ const RegionsMixin = types
e && e.stopPropagation();
},

notifyDrawingFinished({ destroy = false } = {}) {
updateOriginOnEdit() {
if (self.origin === "prediction") {
self.origin = "prediction-changed";
}
},

notifyDrawingFinished({ destroy = false } = {}) {
self.updateOriginOnEdit();

// everything below is related to dynamic preannotations
if (!self.shouldNotifyDrawingFinished) return;
Expand Down
1 change: 1 addition & 0 deletions web/libs/editor/src/tags/control/ClassificationBase.js
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,7 @@ const ClassificationBase = types
// update result in the store with current set value
updateResult() {
if (self.result) {
self.result.area.updateOriginOnEdit();
self.result.area.setValue(self);
} else {
if (self.perregion) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
export const allClassificationsConfig = `<View>
<Text name="text" value="$text"></Text>
<Choices name="choices" toName="text" fromPrediction="true">
<Choice value="Choice 1" />
<Choice value="Choice 2" />
</Choices>
<DateTime name="datetime" toName="text"/>
<Number name="number" toName="text"/>
<Rating name="rating" toName="text"/>
<TextArea name="textarea" toName="text"/>
<TextArea name="textarea_edit" toName="text" editable="true" />
</View>`;

export const textData = {
text: "This text exists for no reason",
};

export const prediction = {
id: "223322223322",
result: [
{
id: "1",
from_name: "choices",
to_name: "text",
type: "choices",
value: {
choices: ["Choice 1"],
},
},
{
id: "2",
from_name: "datetime",
to_name: "text",
type: "datetime",
value: {
datetime: "2000-01-01T00:00:00.000Z",
},
},
{
id: "3",
from_name: "number",
to_name: "text",
type: "number",
value: {
number: 3.14,
},
},
{
id: "4",
from_name: "rating",
to_name: "text",
type: "rating",
value: {
rating: 3,
},
},
{
id: "5",
from_name: "textarea",
to_name: "text",
type: "textarea",
value: {
text: ["This is a text"],
},
},
{
id: "5",
from_name: "textarea_edit",
to_name: "text",
type: "textarea",
value: {
text: ["This text will be"],
},
},
],
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
import {
Choices,
DateTime,
LabelStudio,
Number,
Rating,
Textarea,
ToolBar,
useTextarea,
} from "@humansignal/frontend-test/helpers/LSF";
import { Hotkeys } from "@humansignal/frontend-test/helpers/LSF/Hotkeys";
import { FF_DEV_3873 } from "../../../../src/utils/feature-flags";
import { allClassificationsConfig, prediction, textData } from "../../data/control_tags/from-prediction";

describe("Classification from prediction", () => {
it('by default should have origin "prediction"', () => {
LabelStudio.params().config(allClassificationsConfig).data(textData).withPrediction(prediction).init();
LabelStudio.waitForObjectsReady();
LabelStudio.serialize().then((results) => {
for (const result of results) {
expect(result.origin).to.equal("prediction");
}
});
});

it('should have origin "prediction-changed" after changing prediction', () => {
const SecondTextarea = useTextarea("&:eq(1)");
LabelStudio.addFeatureFlagsOnPageLoad({
[FF_DEV_3873]: true,
});
LabelStudio.params().config(allClassificationsConfig).data(textData).withPrediction(prediction).init();
LabelStudio.waitForObjectsReady();
ToolBar.clickCopyAnnotationBtn();
LabelStudio.waitForObjectsReady();
Choices.findChoice("Choice 2").click();
DateTime.type("1999-11-11T11:11:11.111Z");
Number.type("123");
Rating.setValue(2);
Textarea.type("Some other text{Enter}");
SecondTextarea.clickRowEdit(1);
SecondTextarea.rowInput(1).dblclick();
SecondTextarea.rowType(1, " longer at the end{Enter}");
LabelStudio.serialize().then((results) => {
for (const result of results) {
expect(result.origin).to.equal(
"prediction-changed",
`Prediction origin was not updated for "${result.from_name}"`,
);
}
});
});

it("should work correctly with undo", () => {
const SecondTextarea = useTextarea("&:eq(1)");
LabelStudio.addFeatureFlagsOnPageLoad({
[FF_DEV_3873]: true,
});
LabelStudio.params().config(allClassificationsConfig).data(textData).withPrediction(prediction).init();
LabelStudio.waitForObjectsReady();
ToolBar.clickCopyAnnotationBtn();
LabelStudio.waitForObjectsReady();
Choices.findChoice("Choice 2").click();
DateTime.type("1999-11-11T11:11:11.111Z");
Number.type("1");
Rating.setValue(2);
Textarea.type("Some other text{Enter}");
SecondTextarea.clickRowEdit(1);
SecondTextarea.rowInput(1).dblclick();
SecondTextarea.rowType(1, " longer at the end{Enter}");
for (let i = 0; i < 6; i++) {
Hotkeys.undo();
}
LabelStudio.serialize().then((results) => {
for (const result of results) {
expect(result.origin).to.equal("prediction");
}
});
});
});
13 changes: 13 additions & 0 deletions web/libs/frontend-test/src/helpers/LSF/LabelStudio.ts
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,15 @@ class LSParamsBuilder {
return task.annotations;
}

private get _predictions() {
const task = this._task;

if (!task.predictions) {
task.predictions = [];
}
return task.predictions;
}

config(config) {
this.params.config = config;
return this;
Expand All @@ -90,6 +99,10 @@ class LSParamsBuilder {
this._annotations.push(annotation);
return this;
}
withPrediction(prediction) {
this._predictions.push(prediction);
return this;
}
withResult(result) {
this._annotations.push({
id: this._annotations.length + 1001,
Expand Down
32 changes: 28 additions & 4 deletions web/libs/frontend-test/src/helpers/LSF/ToolBar.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,25 +4,49 @@ import { FF_DEV_3873 } from "../../../../editor/src/utils/feature-flags";
export const ToolBar = {
_controlsSelector: ".lsf-controls",

get root() {
get sectionOne() {
return cy.get(".lsf-topbar").find(".lsf-topbar__group").eq(0);
},

get sectionTwo() {
return LabelStudio.getFeatureFlag(FF_DEV_3873).then((isFFDEV3873) => {
if (isFFDEV3873) {
return cy.get(".lsf-bottombar");
}

return cy.get(".lsf-topbar");
return cy.get(".lsf-topbar").find(".lsf-topbar__group").eq(1);
});
},

get controls() {
return this.root.find(this._controlsSelector);
return this.sectionTwo.find(this._controlsSelector);
},

get controlButtons() {
return this.controls.find("button");
},

get submitBtn() {
return this.root.find('[aria-label="submit"]');
return this.sectionTwo.find('[aria-label="submit"]');
},

get annotationDropdownTrigger() {
return this.sectionOne.find(".lsf-annotation-button__trigger");
},

get dropdownMenu() {
return cy.get(".lsf-dropdown");
},

clickCopyAnnotationBtn() {
return LabelStudio.getFeatureFlag(FF_DEV_3873).then((isFFDEV3873) => {
if (isFFDEV3873) {
this.annotationDropdownTrigger.click();
this.dropdownMenu.find('[class*="option--"]').contains("Duplicate Annotation").click();
return void 0;
}

this.sectionOne.find('[aria-label="Copy Annotation"]').click();
});
},
};
Loading