From c34697ce24ff3425c77c8263af03ad2dac8c8ce9 Mon Sep 17 00:00:00 2001 From: Tamir Date: Wed, 8 Jan 2025 10:59:10 +0200 Subject: [PATCH 01/12] Fix `Must provide a proper URL as target` error --- web/webpack.config.js | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/web/webpack.config.js b/web/webpack.config.js index 571339d24a8c..2b3322db7190 100644 --- a/web/webpack.config.js +++ b/web/webpack.config.js @@ -262,13 +262,19 @@ module.exports = composePlugins( publicPath: `${FRONTEND_HOSTNAME}/react-app/`, }, allowedHosts: "all", // Allow access from Django's server - proxy: [ - { - router: { - "/api": `${DJANGO_HOSTNAME}/api`, // Proxy api requests to Django's server - }, + proxy: { + "/api": { + target: `${DJANGO_HOSTNAME}/api`, + changeOrigin: true, + pathRewrite: { "^/api": "" }, + secure: false, }, - ], + "/": { + target: `${DJANGO_HOSTNAME}`, + changeOrigin: true, + secure: false, + }, + }, }, }); }, From 3fdc2b03971c3c9d9fef50ba013bda58cfe81745 Mon Sep 17 00:00:00 2001 From: Tamir Date: Thu, 9 Jan 2025 12:38:34 +0200 Subject: [PATCH 02/12] feat: add URL-based region visibility, hiding all but the specified region on load --- web/libs/datamanager/src/stores/AppStore.js | 67 ++++++++++++++----- .../datamanager/src/utils/feature-flags.js | 5 ++ .../editor/src/core/feature-flags/flags.json | 3 +- web/libs/editor/src/stores/RegionStore.js | 17 +++++ 4 files changed, 76 insertions(+), 16 deletions(-) diff --git a/web/libs/datamanager/src/stores/AppStore.js b/web/libs/datamanager/src/stores/AppStore.js index 78a914305576..a89f1f86fa13 100644 --- a/web/libs/datamanager/src/stores/AppStore.js +++ b/web/libs/datamanager/src/stores/AppStore.js @@ -1,6 +1,6 @@ import { destroy, flow, types } from "mobx-state-tree"; import { Modal } from "../components/Common/Modal/Modal"; -import { FF_DEV_2887, FF_LOPS_E_3, isFF } from "../utils/feature-flags"; +import { FF_DEV_2887, FF_LOPS_E_3, FF_REGION_VISIBILITY_FROM_URL, isFF } from "../utils/feature-flags"; import { History } from "../utils/history"; import { isDefined } from "../utils/utils"; import { Action } from "./Action"; @@ -199,7 +199,22 @@ export const AppStore = types setTask: flow(function* ({ taskID, annotationID, pushState }) { if (pushState !== false) { - History.navigate({ task: taskID, annotation: annotationID ?? null, interaction: null }); + History.navigate({ + task: taskID, + annotation: annotationID ?? null, + interaction: null, + region: null, + }); + } else { + const { task, region, annotation } = History.getParams(); + History.navigate( + { + task, + region, + annotation, + }, + true, + ); } if (!isDefined(taskID)) return; @@ -214,22 +229,39 @@ export const AppStore = types if (annotationID !== undefined) { self.annotationStore.setSelected(annotationID); - } else { - self.taskStore.setSelected(taskID); + } + self.taskStore.setSelected(taskID); - const taskPromise = self.taskStore.loadTask(taskID, { - select: !!taskID && !!annotationID, - }); + const taskPromise = self.taskStore.loadTask(taskID, { + select: !!taskID && !!annotationID, + }); - taskPromise.then(() => { - const annotation = self.LSF?.currentAnnotation; - const id = annotation?.pk ?? annotation?.id; + taskPromise.then(() => { + const annotation = self.LSF?.currentAnnotation; + const id = annotation?.pk ?? annotation?.id; - self.LSF?.setLSFTask(self.taskStore.selected, id); + self.LSF?.setLSFTask(self.taskStore.selected, id); - self.setLoadingData(false); - }); - } + if (isFF(FF_REGION_VISIBILITY_FROM_URL)) { + const { annotation: annIDFromUrl, region: regionIDFromUrl } = History.getParams(); + if (annIDFromUrl) { + const lsfAnnotation = self.LSF.lsf.annotationStore.annotations.find((a) => { + return a.pk === annIDFromUrl || a.id === annIDFromUrl; + }); + + if (lsfAnnotation) { + const annID = lsfAnnotation.pk ?? lsfAnnotation.id; + self.LSF?.setLSFTask(self.taskStore.selected, annID); + } + } + if (regionIDFromUrl) { + const currentAnn = self.LSF?.currentAnnotation; + currentAnn?.regionStore?.setRegionVisible(regionIDFromUrl); + } + } + + self.setLoadingData(false); + }); }), setLoadingData(value) { @@ -379,7 +411,7 @@ export const AppStore = types }, handlePopState: (({ state }) => { - const { tab, task, annotation, labeling } = state ?? {}; + const { tab, task, annotation, labeling, region } = state ?? {}; if (tab) { const tabId = Number.parseInt(tab); @@ -399,6 +431,11 @@ export const AppStore = types } else { params.id = Number.parseInt(task); } + if (region) { + params.region = region; + } else { + delete params.region; + } self.startLabeling(params, { pushState: false }); } else if (labeling) { diff --git a/web/libs/datamanager/src/utils/feature-flags.js b/web/libs/datamanager/src/utils/feature-flags.js index 947bfa8ee4e2..27b1f3fcdda4 100644 --- a/web/libs/datamanager/src/utils/feature-flags.js +++ b/web/libs/datamanager/src/utils/feature-flags.js @@ -73,6 +73,11 @@ export const FF_GRID_PREVIEW = "fflag_feat_front_leap_1424_grid_preview_short"; export const FF_MEMORY_LEAK_FIX = "fflag_feat_all_optic_1178_reduce_memory_leak_short"; +/** + * Add ability to show specific region from URL params (by hiding all other regions). + */ +export const FF_REGION_VISIBILITY_FROM_URL = "fflag_feat_front_region_visibility_from_url_short"; + // Customize flags const flags = {}; diff --git a/web/libs/editor/src/core/feature-flags/flags.json b/web/libs/editor/src/core/feature-flags/flags.json index 834c343148bb..ef3d63202b9c 100644 --- a/web/libs/editor/src/core/feature-flags/flags.json +++ b/web/libs/editor/src/core/feature-flags/flags.json @@ -6,5 +6,6 @@ "fflag_fix_front_dev_3617_taxonomy_memory_leaks_fix": true, "fflag_feat_front_dev_3873_labeling_ui_improvements_short": true, "fflag_feat_front_lsdv_4620_richtext_opimization_060423_short": true, - "fflag_fix_front_lsdv_4620_memory_leaks_100723_short": false + "fflag_fix_front_lsdv_4620_memory_leaks_100723_short": false, + "fflag_feat_front_region_visibility_from_url_short": true } diff --git a/web/libs/editor/src/stores/RegionStore.js b/web/libs/editor/src/stores/RegionStore.js index c31b9cd599d8..deebfa9a2a8f 100644 --- a/web/libs/editor/src/stores/RegionStore.js +++ b/web/libs/editor/src/stores/RegionStore.js @@ -572,6 +572,21 @@ export default types } }); }, + + setRegionVisible(regionId) { + regionId = `${regionId}#${self.annotation.id}`; // LS adds suffix to region id after '#' + const targetRegion = self.regions.find((r) => r.id === regionId); + if (!targetRegion) return; + + self.regions.forEach((area) => { + if (!area.hidden) { + area.toggleHidden(); + } + }); + + targetRegion.toggleHidden(); + }, + setHiddenByTool(shouldBeHidden, label) { self.regions.forEach((area) => { if (area.hidden !== shouldBeHidden && area.type === label.type) { @@ -579,6 +594,7 @@ export default types } }); }, + setHiddenByLabel(shouldBeHidden, label) { self.regions.forEach((area) => { if (area.hidden !== shouldBeHidden) { @@ -594,6 +610,7 @@ export default types } }); }, + highlight(area) { self.selection.highlight(area); }, From 60374d95948a10511535b45a244f21aa39373954 Mon Sep 17 00:00:00 2001 From: Tamir Date: Thu, 23 Jan 2025 00:59:32 +0200 Subject: [PATCH 03/12] Rename feature flag --- web/libs/datamanager/src/utils/feature-flags.js | 2 +- web/libs/editor/src/core/feature-flags/flags.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/web/libs/datamanager/src/utils/feature-flags.js b/web/libs/datamanager/src/utils/feature-flags.js index 27b1f3fcdda4..d8e2cbf8d00a 100644 --- a/web/libs/datamanager/src/utils/feature-flags.js +++ b/web/libs/datamanager/src/utils/feature-flags.js @@ -76,7 +76,7 @@ export const FF_MEMORY_LEAK_FIX = "fflag_feat_all_optic_1178_reduce_memory_leak_ /** * Add ability to show specific region from URL params (by hiding all other regions). */ -export const FF_REGION_VISIBILITY_FROM_URL = "fflag_feat_front_region_visibility_from_url_short"; +export const FF_REGION_VISIBILITY_FROM_URL = "fflag_feat_front_optic_1553_url_based_region_visibility_short"; // Customize flags const flags = {}; diff --git a/web/libs/editor/src/core/feature-flags/flags.json b/web/libs/editor/src/core/feature-flags/flags.json index ef3d63202b9c..295ac84df53d 100644 --- a/web/libs/editor/src/core/feature-flags/flags.json +++ b/web/libs/editor/src/core/feature-flags/flags.json @@ -7,5 +7,5 @@ "fflag_feat_front_dev_3873_labeling_ui_improvements_short": true, "fflag_feat_front_lsdv_4620_richtext_opimization_060423_short": true, "fflag_fix_front_lsdv_4620_memory_leaks_100723_short": false, - "fflag_feat_front_region_visibility_from_url_short": true + "fflag_feat_front_optic_1553_url_based_region_visibility_short": true } From 7ac816fc0205b9cf21598f409aab64d1be32fb50 Mon Sep 17 00:00:00 2001 From: Tamir Date: Tue, 4 Feb 2025 18:14:05 +0200 Subject: [PATCH 04/12] Add test "should hide all regions except the target region by ID from param" --- .../integration/data/outliner/hide-all.ts | 2 +- .../integration/e2e/outliner/hide-all.cy.ts | 33 +++++++++++++++++++ 2 files changed, 34 insertions(+), 1 deletion(-) diff --git a/web/libs/editor/tests/integration/data/outliner/hide-all.ts b/web/libs/editor/tests/integration/data/outliner/hide-all.ts index e49be0559bb9..055ada26bbec 100644 --- a/web/libs/editor/tests/integration/data/outliner/hide-all.ts +++ b/web/libs/editor/tests/integration/data/outliner/hide-all.ts @@ -3,7 +3,7 @@ export const simpleRegionsConfig = ` `; diff --git a/web/libs/editor/tests/integration/e2e/outliner/hide-all.cy.ts b/web/libs/editor/tests/integration/e2e/outliner/hide-all.cy.ts index 062c7b688b84..7e5016ee90db 100644 --- a/web/libs/editor/tests/integration/e2e/outliner/hide-all.cy.ts +++ b/web/libs/editor/tests/integration/e2e/outliner/hide-all.cy.ts @@ -45,6 +45,38 @@ describe("Outliner - Hide all regions", () => { Sidebar.hasHiddenRegion(3); }); + it("should hide all regions except the target region by ID from param", () => { + LabelStudio.params() + .config(simpleRegionsConfig) + .data(simpleRegionsData) + .withResult(simpleRegionsResult) + .withParam("region", "label_2") + .init(); + LabelStudio.setFeatureFlagsOnPageLoad({ + fflag_feat_front_optic_1553_url_based_region_visibility_short: true, + }); + cy.window().then((win) => { + (win as unknown as any).Htx.annotationStore.annotations[0].regionStore.setRegionVisible( + (win as unknown as any).LSF_CONFIG.region, + ); + }); + + Sidebar.hasRegions(3); + Sidebar.hasHiddenRegion(2); + Sidebar.findRegionByIndex(0) + .should("contain.text", "Label 1") + .parent() + .should("have.class", "lsf-tree__node_hidden"); + Sidebar.findRegionByIndex(1) + .should("contain.text", "Label 2") + .parent() + .should("not.have.class", "lsf-tree__node_hidden"); + Sidebar.findRegionByIndex(2) + .should("contain.text", "Label 3") + .parent() + .should("have.class", "lsf-tree__node_hidden"); + }); + it("should have tooltip for hide action", () => { LabelStudio.params().config(simpleRegionsConfig).data(simpleRegionsData).withResult(simpleRegionsResult).init(); @@ -61,6 +93,7 @@ describe("Outliner - Hide all regions", () => { Sidebar.showAllRegionsButton.trigger("mouseenter"); Tooltip.hasText("Show all regions"); }); + it("should react to changes in regions' visibility", () => { LabelStudio.params().config(simpleRegionsConfig).data(simpleRegionsData).withResult(simpleRegionsResult).init(); From 1c26af7cf299d636b662ef010471014faf746396 Mon Sep 17 00:00:00 2001 From: Tamir Date: Wed, 5 Feb 2025 16:44:41 +0200 Subject: [PATCH 05/12] Add more test cases and `assertRegionHidden` helper --- .../integration/e2e/outliner/hide-all.cy.ts | 78 ++++++++++++++----- .../frontend-test/src/helpers/LSF/Sidebar.ts | 4 + 2 files changed, 64 insertions(+), 18 deletions(-) diff --git a/web/libs/editor/tests/integration/e2e/outliner/hide-all.cy.ts b/web/libs/editor/tests/integration/e2e/outliner/hide-all.cy.ts index 7e5016ee90db..a51171981142 100644 --- a/web/libs/editor/tests/integration/e2e/outliner/hide-all.cy.ts +++ b/web/libs/editor/tests/integration/e2e/outliner/hide-all.cy.ts @@ -52,29 +52,71 @@ describe("Outliner - Hide all regions", () => { .withResult(simpleRegionsResult) .withParam("region", "label_2") .init(); - LabelStudio.setFeatureFlagsOnPageLoad({ - fflag_feat_front_optic_1553_url_based_region_visibility_short: true, + + cy.window().then((window: any | unknown) => { + window.Htx.annotationStore.annotations[0].regionStore.setRegionVisible(window.LSF_CONFIG.region); }); - cy.window().then((win) => { - (win as unknown as any).Htx.annotationStore.annotations[0].regionStore.setRegionVisible( - (win as unknown as any).LSF_CONFIG.region, - ); + + Sidebar.hasRegions(3); + Sidebar.hasHiddenRegion(2); + + Sidebar.assertRegionHidden(0, "Label 1", true); + Sidebar.assertRegionHidden(1, "Label 2", false); + Sidebar.assertRegionHidden(2, "Label 3", true); + }); + + it("should hide all regions except the target region by ID within the targeted annotation tab specified by param", () => { + LabelStudio.params() + .config(simpleRegionsConfig) + .data(simpleRegionsData) + .withAnnotation({ id: "10", result: simpleRegionsResult }) + .withAnnotation({ id: "20", result: simpleRegionsResult }) + .withParam("annotation", "10") + .withParam("region", "label_2") + .init(); + + cy.window().then((window: any | unknown) => { + const annIdFromParam = window.LSF_CONFIG.annotation; + const annotations = window.Htx.annotationStore.annotations; + const lsfAnnotation = annotations.find((ann: any) => ann.pk === annIdFromParam || ann.id === annIdFromParam); + const annID = lsfAnnotation.pk ?? lsfAnnotation.id; + + expect(annID).to.equal("10"); + + // Move to the annotation tab specified by param + cy.get('[class="lsf-annotations-list__toggle"]').click(); + cy.get('[class="lsf-annotations-list__entity-id"]').contains("10").click(); + + annotations[1].regionStore.setRegionVisible(window.LSF_CONFIG.region); }); Sidebar.hasRegions(3); Sidebar.hasHiddenRegion(2); - Sidebar.findRegionByIndex(0) - .should("contain.text", "Label 1") - .parent() - .should("have.class", "lsf-tree__node_hidden"); - Sidebar.findRegionByIndex(1) - .should("contain.text", "Label 2") - .parent() - .should("not.have.class", "lsf-tree__node_hidden"); - Sidebar.findRegionByIndex(2) - .should("contain.text", "Label 3") - .parent() - .should("have.class", "lsf-tree__node_hidden"); + + Sidebar.assertRegionHidden(0, "Label 1", true); + Sidebar.assertRegionHidden(1, "Label 2", false); + Sidebar.assertRegionHidden(2, "Label 3", true); + }); + + it("should not hide regions in the non-targeted annotaion tab", () => { + LabelStudio.params() + .config(simpleRegionsConfig) + .data(simpleRegionsData) + .withAnnotation({ id: "10", result: simpleRegionsResult }) + .withAnnotation({ id: "20", result: simpleRegionsResult }) + .withParam("annotation", "10") + .withParam("region", "label_2") + .init(); + + cy.window().then((window: any | unknown) => { + window.Htx.annotationStore.annotations[1].regionStore.setRegionVisible(window.LSF_CONFIG.region); + }); + + // Validate the annotation tab + cy.get('[class="lsf-annotations-list__entity-id"]').should("contain.text", "20"); + + Sidebar.hasRegions(3); + Sidebar.hasHiddenRegion(0); }); it("should have tooltip for hide action", () => { diff --git a/web/libs/frontend-test/src/helpers/LSF/Sidebar.ts b/web/libs/frontend-test/src/helpers/LSF/Sidebar.ts index 8f81b47bf95e..00fc21bca0ca 100644 --- a/web/libs/frontend-test/src/helpers/LSF/Sidebar.ts +++ b/web/libs/frontend-test/src/helpers/LSF/Sidebar.ts @@ -77,4 +77,8 @@ export const Sidebar = { expandDetailsRightPanel() { cy.get(".lsf-sidepanels__wrapper_align_right .lsf-panel__header").should("be.visible").click(); }, + assertRegionHidden(idx: number, id: string, shouldBeHidden: boolean) { + const expectation = shouldBeHidden ? "have.class" : "not.have.class"; + this.findRegionByIndex(idx).should("contain.text", id).parent().should(expectation, "lsf-tree__node_hidden"); + }, }; From 06aa044b0b1e667b78ce006edbd1ce4faf84f82f Mon Sep 17 00:00:00 2001 From: Tamir Date: Wed, 5 Feb 2025 17:24:10 +0200 Subject: [PATCH 06/12] Remove the feature flag from the editor folder --- web/libs/editor/src/core/feature-flags/flags.json | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/web/libs/editor/src/core/feature-flags/flags.json b/web/libs/editor/src/core/feature-flags/flags.json index 295ac84df53d..834c343148bb 100644 --- a/web/libs/editor/src/core/feature-flags/flags.json +++ b/web/libs/editor/src/core/feature-flags/flags.json @@ -6,6 +6,5 @@ "fflag_fix_front_dev_3617_taxonomy_memory_leaks_fix": true, "fflag_feat_front_dev_3873_labeling_ui_improvements_short": true, "fflag_feat_front_lsdv_4620_richtext_opimization_060423_short": true, - "fflag_fix_front_lsdv_4620_memory_leaks_100723_short": false, - "fflag_feat_front_optic_1553_url_based_region_visibility_short": true + "fflag_fix_front_lsdv_4620_memory_leaks_100723_short": false } From 1a602fe73af89ca720c49e5a6c4c419b2e36fff5 Mon Sep 17 00:00:00 2001 From: Tamir Date: Wed, 5 Feb 2025 18:38:52 +0200 Subject: [PATCH 07/12] Applied bmartel suggestion --- web/libs/datamanager/src/stores/AppStore.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/web/libs/datamanager/src/stores/AppStore.js b/web/libs/datamanager/src/stores/AppStore.js index a89f1f86fa13..bc5889c8d15a 100644 --- a/web/libs/datamanager/src/stores/AppStore.js +++ b/web/libs/datamanager/src/stores/AppStore.js @@ -205,7 +205,7 @@ export const AppStore = types interaction: null, region: null, }); - } else { + } else if (isFF(FF_REGION_VISIBILITY_FROM_URL)) { const { task, region, annotation } = History.getParams(); History.navigate( { From 04bb68ef0fc43d288e3937b8ddbbad9f09a16d60 Mon Sep 17 00:00:00 2001 From: Tamir Date: Thu, 6 Feb 2025 14:53:53 +0200 Subject: [PATCH 08/12] Revert removal of `else` case in `setTask` --- web/libs/datamanager/src/stores/AppStore.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/web/libs/datamanager/src/stores/AppStore.js b/web/libs/datamanager/src/stores/AppStore.js index bc5889c8d15a..147b74eb672e 100644 --- a/web/libs/datamanager/src/stores/AppStore.js +++ b/web/libs/datamanager/src/stores/AppStore.js @@ -229,8 +229,9 @@ export const AppStore = types if (annotationID !== undefined) { self.annotationStore.setSelected(annotationID); + } else { + self.taskStore.setSelected(taskID); } - self.taskStore.setSelected(taskID); const taskPromise = self.taskStore.loadTask(taskID, { select: !!taskID && !!annotationID, From 9331b2daa095a596ceee9e07359c0929d6d8df82 Mon Sep 17 00:00:00 2001 From: Brandon Martel Date: Fri, 7 Feb 2025 09:27:26 -0600 Subject: [PATCH 09/12] small refactor for clarity, adding selection state so details panel is visible on navigation --- web/libs/datamanager/src/stores/AppStore.js | 3 +++ web/libs/editor/src/stores/RegionStore.js | 22 ++++++++++++++++++--- 2 files changed, 22 insertions(+), 3 deletions(-) diff --git a/web/libs/datamanager/src/stores/AppStore.js b/web/libs/datamanager/src/stores/AppStore.js index 147b74eb672e..352b0e22c9a4 100644 --- a/web/libs/datamanager/src/stores/AppStore.js +++ b/web/libs/datamanager/src/stores/AppStore.js @@ -257,7 +257,10 @@ export const AppStore = types } if (regionIDFromUrl) { const currentAnn = self.LSF?.currentAnnotation; + // Focus on the region by hiding all other regions currentAnn?.regionStore?.setRegionVisible(regionIDFromUrl); + // Select the region so outliner details are visible + currentAnn?.regionStore?.selectRegionByID(regionIDFromUrl); } } diff --git a/web/libs/editor/src/stores/RegionStore.js b/web/libs/editor/src/stores/RegionStore.js index 9e17ba948b12..35b1147bca7b 100644 --- a/web/libs/editor/src/stores/RegionStore.js +++ b/web/libs/editor/src/stores/RegionStore.js @@ -507,17 +507,26 @@ export default types }, findRegionID(id) { + if (!id) return null; return self.regions.find((r) => r.id === id); }, findRegion(id) { - return self.regions.find((r) => r.id === id); + return self.findRegionID(id); }, filterByParentID(id) { return self.regions.filter((r) => r.parentID === id); }, + normalizeRegionId(regionId) { + if (!regionId) return ""; + if (!regionId.includes("#")) { + regionId = `${regionId}#${self.annotation.id}`; + } + return regionId; + }, + afterCreate() { onPatch(self, (patch) => { if ((patch.op === "add" || patch.op === "delete") && patch.path.indexOf("/regions/") !== -1) { @@ -583,9 +592,16 @@ export default types }); }, + selectRegionByID(regionId) { + const normalizedRegionId = self.normalizeRegionId(regionId); + const targetRegion = self.findRegionID(normalizedRegionId); + if (!targetRegion) return; + self.toggleSelection(targetRegion, true); + }, + setRegionVisible(regionId) { - regionId = `${regionId}#${self.annotation.id}`; // LS adds suffix to region id after '#' - const targetRegion = self.regions.find((r) => r.id === regionId); + const normalizedRegionId = self.normalizeRegionId(regionId); + const targetRegion = self.findRegionID(normalizedRegionId); if (!targetRegion) return; self.regions.forEach((area) => { From 6fbc6db922aa91358a2a5aa412361311616c9290 Mon Sep 17 00:00:00 2001 From: Brandon Martel Date: Fri, 7 Feb 2025 09:42:00 -0600 Subject: [PATCH 10/12] move casing to match other surrounding methods --- web/libs/editor/src/stores/RegionStore.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/web/libs/editor/src/stores/RegionStore.js b/web/libs/editor/src/stores/RegionStore.js index 35b1147bca7b..0cf107e5c2db 100644 --- a/web/libs/editor/src/stores/RegionStore.js +++ b/web/libs/editor/src/stores/RegionStore.js @@ -292,7 +292,7 @@ export default types lookup.forEach((el) => { const pid = el.item.parentID; - const parent = pid ? lookup.get(pid) ?? lookup.get(pid.replace(/#(.+)/i, "")) : null; + const parent = pid ? (lookup.get(pid) ?? lookup.get(pid.replace(/#(.+)/i, ""))) : null; if (parent) return parent.children.push(el); @@ -519,7 +519,7 @@ export default types return self.regions.filter((r) => r.parentID === id); }, - normalizeRegionId(regionId) { + normalizeRegionID(regionId) { if (!regionId) return ""; if (!regionId.includes("#")) { regionId = `${regionId}#${self.annotation.id}`; @@ -593,14 +593,14 @@ export default types }, selectRegionByID(regionId) { - const normalizedRegionId = self.normalizeRegionId(regionId); + const normalizedRegionId = self.normalizeRegionID(regionId); const targetRegion = self.findRegionID(normalizedRegionId); if (!targetRegion) return; self.toggleSelection(targetRegion, true); }, setRegionVisible(regionId) { - const normalizedRegionId = self.normalizeRegionId(regionId); + const normalizedRegionId = self.normalizeRegionID(regionId); const targetRegion = self.findRegionID(normalizedRegionId); if (!targetRegion) return; From df3f7fd6a20bfd3a2d0809ab8ec21bbd2a55bfb6 Mon Sep 17 00:00:00 2001 From: Brandon Martel Date: Fri, 7 Feb 2025 11:54:11 -0600 Subject: [PATCH 11/12] linting --- web/libs/editor/src/stores/RegionStore.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/web/libs/editor/src/stores/RegionStore.js b/web/libs/editor/src/stores/RegionStore.js index 0cf107e5c2db..2dccb7503f87 100644 --- a/web/libs/editor/src/stores/RegionStore.js +++ b/web/libs/editor/src/stores/RegionStore.js @@ -292,7 +292,7 @@ export default types lookup.forEach((el) => { const pid = el.item.parentID; - const parent = pid ? (lookup.get(pid) ?? lookup.get(pid.replace(/#(.+)/i, ""))) : null; + const parent = pid ? lookup.get(pid) ?? lookup.get(pid.replace(/#(.+)/i, "")) : null; if (parent) return parent.children.push(el); From 4c4c486123ed16696c0c016544d7cc210d377e9a Mon Sep 17 00:00:00 2001 From: Tamir Date: Sun, 9 Feb 2025 11:28:01 +0200 Subject: [PATCH 12/12] Add test: `should select the target region by ID from param` --- .../integration/e2e/outliner/hide-all.cy.ts | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/web/libs/editor/tests/integration/e2e/outliner/hide-all.cy.ts b/web/libs/editor/tests/integration/e2e/outliner/hide-all.cy.ts index a51171981142..2f3bda4aed1e 100644 --- a/web/libs/editor/tests/integration/e2e/outliner/hide-all.cy.ts +++ b/web/libs/editor/tests/integration/e2e/outliner/hide-all.cy.ts @@ -119,6 +119,23 @@ describe("Outliner - Hide all regions", () => { Sidebar.hasHiddenRegion(0); }); + it("should select the target region by ID from param", () => { + LabelStudio.params() + .config(simpleRegionsConfig) + .data(simpleRegionsData) + .withResult(simpleRegionsResult) + .withParam("region", "label_2") + .init(); + + cy.window().then((window: any | unknown) => { + window.Htx.annotationStore.annotations[0].regionStore.selectRegionByID(window.LSF_CONFIG.region); + }); + + Sidebar.hasRegions(3); + Sidebar.hasSelectedRegions(1); + Sidebar.hasSelectedRegion(1); + }); + it("should have tooltip for hide action", () => { LabelStudio.params().config(simpleRegionsConfig).data(simpleRegionsData).withResult(simpleRegionsResult).init();