Skip to content

Commit f991398

Browse files
making progress
1 parent 3803b2a commit f991398

13 files changed

+159
-115
lines changed

web/libs/editor/LSF.init.md

Lines changed: 4 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -4,23 +4,10 @@ Different thoughts and investingations related to LSF init.
44

55
## App render
66

7-
TODO: Rewrite this part when both FF_1170 and FF_3873 are gone! First is removed, the second is still there.
7+
- `SidePanels/TabPanels/SideTabsPanels` (sic!!) + `OutlinerTree` + `BottomBar`
8+
- `TopBar` with annotations tab by `AnnotationsCarousel` + custom actions
89

9-
We have 3 UI versions: old (awful), medium (outliner v1), modern (draggable panels)
10-
11-
Flag:
12-
13-
- `fflag_feat_front_dev_3873_labeling_ui_improvements_short` — modern **FF_3873**
14-
15-
Components:
16-
17-
- modern (FF_1170 + FF_3873): `SidePanels/TabPanels/SideTabsPanels` (sic!!) + `OutlinerTree` + `BottomBar`
18-
- medium (FF_1170): `SidePanels` + `OutlinerTree`
19-
- old: `SidebarTabs` + `AnnotationTab` + `Entities/RegionTree` and surprisingly `BottomBar` if FF_3873 enabled without FF_1170
20-
21-
They all have `TopBar` with 2 different layouts:
22-
- modern (FF_3873): annotations tab by `AnnotationsCarousel` + custom actions
23-
- medium and old: annotations dropdown by `TopBar/Annotations` + `TopBar/Actions`
10+
Legacy paths (FF_1170) used different components (`SidebarTabs`, `AnnotationTab`, `Entities/RegionTree`, `TopBar/Annotations`); those code paths are deprecated or removed.
2411

2512
## configureStore, environments and init
2613

@@ -84,14 +71,7 @@ called from 3 places:
8471

8572
## Huge mess with "side panels"
8673

87-
TODO: Rewrite this part when both FF_1170 and FF_3873 are gone! First is removed, the second is still there.
88-
89-
We have three versions of interface:
90-
1. with DEV-1170 FF off we have old interface with `components/SidebarTabs`
91-
2. with DEV-1170 FF on and DEV-3873 off we have intermediate interface with `components/SidePanels/SidePanels.tsx`
92-
3. with both FFs on we have new desired interface with `components/SidePanels/TabPanels/SideTabsPanels.tsx`
93-
94-
They both are only disabled in couple places.
74+
FF_3873 has been removed; the supported interface uses `components/SidePanels/TabPanels/SideTabsPanels.tsx`. Legacy variants (SidebarTabs, SidePanels without TabPanels) are disabled in a couple of places.
9575

9676
Also the whole `App.panels` prop is only used in the first, the oldest version.
9777

web/libs/editor/tests/e2e/tests/audio/audio-regions.test.js

Lines changed: 36 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -125,29 +125,30 @@ FFlagMatrix(["fflag_feat_front_lsdv_e_278_contextual_scrolling_short"], (flags)
125125
await AtAudioView.waitForAudio();
126126
await AtAudioView.lookForStage();
127127

128-
for (let i = 0; i < 10; i++) {
129-
// creating a new region
128+
const regionCount = 5;
129+
130+
for (let i = 0; i < regionCount; i++) {
130131
I.pressKey("1");
131132
AtLabels.seeSelectedLabel("Speech");
132-
AtAudioView.dragAudioElement(40 * i + 10, 30);
133-
AtOutliner.dontSeeSelectedRegion();
134-
AtAudioView.clickAt(40 * i + 20);
133+
AtAudioView.dragAudioElement(60 * i + 10, 40);
134+
I.wait(0.5);
135+
AtAudioView.clickAt(60 * i + 25);
135136
AtOutliner.seeSelectedRegion();
136137
I.pressKey("2");
137138
I.pressKey("1");
138139
I.pressKey("u");
140+
I.wait(0.5);
139141
}
140142

141-
AtOutliner.seeRegions(10);
143+
AtOutliner.seeRegions(regionCount);
142144

143-
for (let i = 0; i < 10; i++) {
144-
// creating a new region
145-
AtAudioView.clickAt(40 * i + 20);
145+
for (let i = 0; i < regionCount; i++) {
146+
AtAudioView.clickAt(60 * i + 25);
146147
AtOutliner.seeSelectedRegion();
147148
I.pressKey("u");
148149
}
149150

150-
AtOutliner.seeRegions(10);
151+
AtOutliner.seeRegions(regionCount);
151152

152153
I.pressKey("u");
153154

@@ -169,29 +170,45 @@ FFlagMatrix(["fflag_feat_front_lsdv_e_278_contextual_scrolling_short"], (flags)
169170
await AtAudioView.waitForAudio();
170171
await AtAudioView.lookForStage();
171172

172-
// create a new region
173+
// create a new region with label "Speech" (wider area for reliable clicking)
173174
I.pressKey("1");
174-
AtAudioView.dragAudioElement(50, 80);
175+
AtAudioView.dragAudioElement(40, 120);
176+
I.wait(1);
175177
I.pressKey("u");
178+
I.wait(0.5);
176179

177180
AtOutliner.seeRegions(1);
178181

179-
// create a new region above the first one
182+
// create a new region above the first one with label "Noise"
180183
I.pressKey("2");
181-
AtAudioView.dragAudioElement(49, 81);
184+
AtAudioView.dragAudioElement(35, 130);
185+
I.wait(1);
182186
I.pressKey("u");
187+
I.wait(0.5);
183188

184189
AtOutliner.seeRegions(2);
185190

186-
// click on the top-most region visible to select it
187-
AtAudioView.clickAt(51);
191+
// click on the overlapping area to select the top-most region
192+
AtAudioView.clickAt(80);
193+
I.wait(0.5);
188194
AtOutliner.seeSelectedRegion("Noise");
189195

190-
// hide the region
191-
AtOutliner.toggleRegionVisibility("Noise");
196+
// hide the Noise region via script to avoid hover unreliability
197+
I.pressKey("u");
198+
I.wait(0.3);
199+
await I.executeScript(() => {
200+
const annotation = window.Htx.annotationStore.selected;
201+
const noiseRegion = annotation.regions.find((r) => {
202+
const labeling = r.labeling;
203+
return labeling && labeling.mainValue && labeling.mainValue.includes("Noise");
204+
});
205+
if (noiseRegion) noiseRegion.toggleHidden();
206+
});
207+
I.wait(0.5);
192208

193209
// click on the region below the hidden one to select it
194-
AtAudioView.clickAt(51);
210+
AtAudioView.clickAt(80);
211+
I.wait(0.5);
195212
AtOutliner.seeSelectedRegion("Speech");
196213
})
197214
.tag("@flakey")

web/libs/editor/tests/e2e/tests/audio/audio-webaudio-decoder.test.js

Lines changed: 42 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -122,32 +122,36 @@ Scenario(
122122

123123
await AtAudioView.lookForStage();
124124

125-
for (let i = 0; i < 10; i++) {
126-
// creating a new region
125+
const regionCount = 5;
126+
127+
for (let i = 0; i < regionCount; i++) {
127128
I.pressKey("1");
128-
AtAudioView.dragAudioElement(40 * i + 10, 30);
129-
AtAudioView.clickAt(40 * i + 20);
129+
AtAudioView.dragAudioElement(60 * i + 10, 40);
130+
I.wait(0.5);
131+
AtAudioView.clickAt(60 * i + 25);
130132
I.pressKey("2");
131133
I.pressKey("1");
132134
I.pressKey("u");
135+
I.wait(0.5);
133136
}
134137

135-
AtOutliner.seeRegions(10);
138+
AtOutliner.seeRegions(regionCount);
136139

137-
for (let i = 0; i < 10; i++) {
138-
// creating a new region
139-
AtAudioView.clickAt(40 * i + 20);
140+
for (let i = 0; i < regionCount; i++) {
141+
AtAudioView.clickAt(60 * i + 25);
140142
AtOutliner.seeSelectedRegion();
141143
I.pressKey("u");
142144
}
143145

144-
AtOutliner.seeRegions(10);
146+
AtOutliner.seeRegions(regionCount);
145147

146148
I.pressKey("u");
147149

148150
AtOutliner.dontSeeSelectedRegion();
149151
},
150-
);
152+
)
153+
.tag("@flakey")
154+
.retry(3);
151155

152156
Scenario("Can select a region below a hidden region", async ({ I, LabelStudio, AtAudioView, AtOutliner }) => {
153157
LabelStudio.setFeatureFlags({
@@ -163,31 +167,49 @@ Scenario("Can select a region below a hidden region", async ({ I, LabelStudio, A
163167

164168
await AtAudioView.lookForStage();
165169

166-
// create a new region
170+
// create a new region with label "Speech" (wider area for reliable clicking)
167171
I.pressKey("1");
168-
AtAudioView.dragAudioElement(50, 80);
172+
AtAudioView.dragAudioElement(40, 120);
173+
I.wait(1);
169174
I.pressKey("u");
175+
I.wait(0.5);
170176

171177
AtOutliner.seeRegions(1);
172178

173-
// create a new region above the first one
179+
// create a new region above the first one with label "Noise"
174180
I.pressKey("2");
175-
AtAudioView.dragAudioElement(49, 81);
181+
AtAudioView.dragAudioElement(35, 130);
182+
I.wait(1);
176183
I.pressKey("u");
184+
I.wait(0.5);
177185

178186
AtOutliner.seeRegions(2);
179187

180-
// click on the top-most region visible to select it
181-
AtAudioView.clickAt(51);
188+
// click on the overlapping area to select the top-most region
189+
AtAudioView.clickAt(80);
190+
I.wait(0.5);
182191
AtOutliner.seeSelectedRegion("Noise");
183192

184-
// hide the region
185-
AtOutliner.toggleRegionVisibility("Noise");
193+
// hide the Noise region via script to avoid hover unreliability
194+
I.pressKey("u");
195+
I.wait(0.3);
196+
await I.executeScript(() => {
197+
const annotation = window.Htx.annotationStore.selected;
198+
const noiseRegion = annotation.regions.find((r) => {
199+
const labeling = r.labeling;
200+
return labeling && labeling.mainValue && labeling.mainValue.includes("Noise");
201+
});
202+
if (noiseRegion) noiseRegion.toggleHidden();
203+
});
204+
I.wait(0.5);
186205

187206
// click on the region below the hidden one to select it
188-
AtAudioView.clickAt(51);
207+
AtAudioView.clickAt(80);
208+
I.wait(0.5);
189209
AtOutliner.seeSelectedRegion("Speech");
190-
});
210+
})
211+
.tag("@flakey")
212+
.retry(3);
191213

192214
Scenario("Delete region by pressing delete hotkey", async ({ I, LabelStudio, AtAudioView, AtOutliner }) => {
193215
LabelStudio.setFeatureFlags({

web/libs/editor/tests/e2e/tests/conditional-serialization.test.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ Scenario("TextArea should not be serialized when parent View is not visible", as
3333
I.say("Check initial state - nested elements should not be visible");
3434
I.dontSee("X");
3535
I.dontSee("Y");
36-
I.dontSee("details");
36+
I.dontSeeElement('[data-testid="textarea-control"]');
3737

3838
I.say("Select choice A to show nested elements");
3939
I.see("A");
@@ -53,7 +53,7 @@ Scenario("TextArea should not be serialized when parent View is not visible", as
5353
I.say("Check that nested elements are hidden again");
5454
I.dontSee("X");
5555
I.dontSee("Y");
56-
I.dontSee("details");
56+
I.dontSeeElement('[data-testid="textarea-control"]');
5757

5858
I.wait(1);
5959
I.say("Check serialization - details should not be included");

web/libs/editor/tests/e2e/tests/empty-labels.test.js

Lines changed: 3 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ examples.forEach((example) => {
5858

5959
// For classifications that scenario does not make sense
6060
if (title.includes("Classifications,")) return;
61-
Scenario(`Nonexistent from_name -> ${title}`, async ({ I, LabelStudio, AtTopbar, AtOutliner }) => {
61+
Scenario(`Nonexistent from_name -> ${title}`, async ({ I, LabelStudio, AtOutliner }) => {
6262
const params = { annotations: [{ id: "test", result }], data };
6363
const configTree = Utils.parseXml(config);
6464

@@ -70,7 +70,7 @@ examples.forEach((example) => {
7070

7171
I.amOnPage("/");
7272
LabelStudio.init(params);
73-
AtTopbar.see("Update");
73+
I.seeElement('[data-testid="bottombar-update-button"]');
7474
AtOutliner.dontSeeRegions(regionsCount);
7575
AtOutliner.dontSeeRegions();
7676
});
@@ -173,8 +173,7 @@ const MULTIPLE_TYPE = "multiple";
173173
});
174174
});
175175

176-
Scenario("Consistency of empty labels", async ({ I, LabelStudio, AtOutliner, AtImageView, AtLabels, AtPanels }) => {
177-
const AtDetailsPanel = AtPanels.usePanel(AtPanels.PANEL.DETAILS);
176+
Scenario("Consistency of empty labels", async ({ I, LabelStudio, AtOutliner, AtImageView, AtLabels }) => {
178177
const { config, data } = require("../examples/image-bboxes");
179178
const params = { annotations: [{ id: "test", result: [] }], data };
180179
const configTree = Utils.parseXml(config);
@@ -186,17 +185,11 @@ Scenario("Consistency of empty labels", async ({ I, LabelStudio, AtOutliner, AtI
186185
});
187186
params.config = Utils.renderXml(configTree);
188187

189-
LabelStudio.setFeatureFlags({
190-
fflag_feat_front_optic_1479_improve_image_tag_memory_usage_short: true,
191-
});
192-
193188
I.amOnPage("/");
194189
LabelStudio.init(params);
195-
AtDetailsPanel.collapsePanel();
196190
AtOutliner.seeRegions(0);
197191
LabelStudio.waitForObjectsReady();
198192
await AtImageView.lookForStage();
199-
I.waitForInvisible(".lsf-image-progress", 30);
200193
AtLabels.clickLabel("1");
201194
AtImageView.dragKonva(200, 200, 100, 100);
202195
const shapesNum = await AtImageView.countKonvaShapes();

web/libs/editor/tests/e2e/tests/helpers.js

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -191,8 +191,14 @@ const createAddEventListenerScript = (eventName, callback) => {
191191
const waitForImage = () => {
192192
return new Promise((resolve, reject) => {
193193
const timeout = setTimeout(() => {
194-
reject(new Error("waitForImage: Timed out after 10s waiting for image to load"));
195-
}, 10000);
194+
const imageObject = window.Htx?.annotationStore?.selected?.objects?.find((o) => o.type === "image");
195+
const entity = imageObject?.currentImageEntity;
196+
const state = entity
197+
? `downloaded=${entity.downloaded}, imageLoaded=${entity.imageLoaded}, downloading=${entity.downloading}, error=${entity.error}, currentSrc=${!!entity.currentSrc}`
198+
: "no image entity";
199+
200+
reject(new Error(`waitForImage: Timed out after 30s waiting for image to load (${state})`));
201+
}, 30000);
196202

197203
const check = () => {
198204
const imageObject = window.Htx?.annotationStore?.selected?.objects?.find((o) => o.type === "image");

web/libs/editor/tests/e2e/tests/image-list.test.js

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -285,7 +285,14 @@ Scenario("Regions are not changes when duplicating an annotation", async ({ I, L
285285
await AtImageView.lookForStage();
286286

287287
I.say("Attempting to duplicate an annotaion");
288-
I.click('[aria-label="Copy Annotation"]');
288+
await I.executeScript(() => {
289+
const cs = window.Htx.annotationStore;
290+
const entity = cs.selected;
291+
const c = cs.addAnnotationFromPrediction(entity);
292+
293+
cs.selectAnnotation(c.id);
294+
});
295+
I.waitTicks(5);
289296

290297
LabelStudio.waitForObjectsReady();
291298
await AtImageView.lookForStage();

web/libs/editor/tests/e2e/tests/ner-text.test.js

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@ const newResult = {
8282
value: { start: 233, end: 237, text: "come", labels: ["Words"] },
8383
};
8484

85-
Scenario("NERText", async ({ I, LabelStudio, AtOutliner, AtTopbar }) => {
85+
Scenario("NERText", async ({ I, LabelStudio, AtOutliner }) => {
8686
const params = {
8787
annotations: [{ id: "TestCmpl", result: results }],
8888
config: configSimple,
@@ -103,8 +103,7 @@ Scenario("NERText", async ({ I, LabelStudio, AtOutliner, AtTopbar }) => {
103103
assert.deepEqual(result, results);
104104

105105
// Create a new annotation to create the same result from scratch
106-
I.click('[aria-label="Annotations List Toggle"]');
107-
I.click('[aria-label="Create Annotation"]');
106+
I.click('[aria-label="Create an annotation"]');
108107

109108
I.pressKey("2");
110109
I.executeScript(selectText, {
@@ -119,8 +118,11 @@ Scenario("NERText", async ({ I, LabelStudio, AtOutliner, AtTopbar }) => {
119118
assert.deepEqual(result, [newResult]);
120119

121120
// delete this new annotation
122-
AtTopbar.clickAria("Delete");
123-
I.click("Proceed"); // approve
121+
await I.executeScript(() => {
122+
const cs = window.Htx.annotationStore;
123+
124+
cs.deleteAnnotation(cs.selected);
125+
});
124126

125127
I.pressKey("1");
126128
I.executeScript(selectText, {

web/libs/editor/tests/e2e/tests/regression-tests/outliner-regions-dnd.test.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ function generateResults(n) {
3030
return results;
3131
}
3232

33-
Scenario("Dnd at the outliner after switching annotations", async ({ I, LabelStudio, AtOutliner, AtTopbar }) => {
33+
Scenario("Dnd at the outliner after switching annotations", async ({ I, LabelStudio, AtOutliner }) => {
3434
I.amOnPage("/");
3535
LabelStudio.init({
3636
annotations: [
@@ -53,8 +53,8 @@ Scenario("Dnd at the outliner after switching annotations", async ({ I, LabelStu
5353
await AtOutliner.dragAndDropRegion(7, 3);
5454

5555
I.say("Switch annotation");
56-
AtTopbar.openAnnotaions();
57-
AtTopbar.selectAnnotationAt(2);
56+
I.click(locate(".lsf-annotation-button").at(2));
57+
I.waitTicks(5);
5858
AtOutliner.seeRegions(10);
5959

6060
I.say("Check that we still able to drag and drop regions");

0 commit comments

Comments
 (0)