From 8a60cd3fe8e6817e9550d4edb67de25bc27ba9eb Mon Sep 17 00:00:00 2001 From: Philipp Otto Date: Tue, 27 Sep 2022 12:36:19 +0200 Subject: [PATCH] Fix validation of layer selection when trying to start globalization of floodfills (#6497) * fix validation of layer selection when trying to start globalization of floodfills * always show globalize-floodfill button and explain when it's disabled * update changelog --- CHANGELOG.unreleased.md | 1 + .../view/action-bar/download_modal_view.tsx | 2 +- .../right-border-tabs/bounding_box_tab.tsx | 88 +++++++++++++------ .../right-border-tabs/starting_job_modals.tsx | 15 ++-- 4 files changed, 73 insertions(+), 33 deletions(-) diff --git a/CHANGELOG.unreleased.md b/CHANGELOG.unreleased.md index 3801966ac48..212087a38d9 100644 --- a/CHANGELOG.unreleased.md +++ b/CHANGELOG.unreleased.md @@ -39,6 +39,7 @@ For upgrade instructions, please check the [migration guide](MIGRATIONS.released - Fixed loading agglomeate skeletons for agglomerate ids larger than 2^31. [#6472](https://github.com/scalableminds/webknossos/pull/6472) - Fixed bug which could lead to conflict-warnings even though there weren't any. [#6477](https://github.com/scalableminds/webknossos/pull/6477) - Fixed that one could not change the color of a segment or tree in Firefox. [#6488](https://github.com/scalableminds/webknossos/pull/6488) +- Fixed validation of layer selection when trying to start globalization of floodfills. [#6497](https://github.com/scalableminds/webknossos/pull/6497) - Fixed filtering for public datasets in dataset table. [#6496](https://github.com/scalableminds/webknossos/pull/6496) ### Removed diff --git a/frontend/javascripts/oxalis/view/action-bar/download_modal_view.tsx b/frontend/javascripts/oxalis/view/action-bar/download_modal_view.tsx index 164dbfbab52..6213621c979 100644 --- a/frontend/javascripts/oxalis/view/action-bar/download_modal_view.tsx +++ b/frontend/javascripts/oxalis/view/action-bar/download_modal_view.tsx @@ -424,7 +424,7 @@ with wk.webknossos_context( diff --git a/frontend/javascripts/oxalis/view/right-border-tabs/bounding_box_tab.tsx b/frontend/javascripts/oxalis/view/right-border-tabs/bounding_box_tab.tsx index c2cc813ee94..b6fd55e2cc7 100644 --- a/frontend/javascripts/oxalis/view/right-border-tabs/bounding_box_tab.tsx +++ b/frontend/javascripts/oxalis/view/right-border-tabs/bounding_box_tab.tsx @@ -18,6 +18,7 @@ import ExportBoundingBoxModal from "oxalis/view/right-border-tabs/export_boundin import * as Utils from "libs/utils"; import features from "features"; import { OxalisState, UserBoundingBox } from "oxalis/store"; +import { APISegmentationLayer, APIUser } from "types/api_flow_types"; // NOTE: The regexp and getBBoxNameForPartialFloodfill need to stay in sync. // That way, bboxes created by the floodfill can be detected as such and @@ -100,11 +101,11 @@ export default function BoundingBoxTab() { setPosition(center); } - const showGlobalizeFloodfillsButton = - features().jobsEnabled && - activeUser != null && - activeSegmentationTracingLayer != null && - userBoundingBoxes.some((bbox) => bbox.name.match(GLOBALIZE_FLOODFILL_REGEX) != null); + const globalizeFloodfillsButtonDisabledReason = getInfoForGlobalizeFloodfill( + userBoundingBoxes, + activeSegmentationTracingLayer, + activeUser, + ); const isViewMode = useSelector( (state: OxalisState) => state.temporaryConfiguration.controlMode === ControlModeEnum.VIEW, @@ -125,27 +126,27 @@ export default function BoundingBoxTab() { minWidth: 300, }} > - {showGlobalizeFloodfillsButton ? ( -
- - - -
- ) : null} +
+ + + +
+ {/* In view mode, it's okay to render an empty list, since there will be an explanation below, anyway. */} @@ -204,3 +205,38 @@ export default function BoundingBoxTab() { ); } + +function getInfoForGlobalizeFloodfill( + userBoundingBoxes: UserBoundingBox[], + activeSegmentationTracingLayer: APISegmentationLayer | null | undefined, + activeUser: APIUser | null | undefined, +) { + if (!userBoundingBoxes.some((bbox) => bbox.name.match(GLOBALIZE_FLOODFILL_REGEX) != null)) { + return { disabled: true, title: "No partial floodfills to globalize." }; + } + if (activeSegmentationTracingLayer == null) { + return { + disabled: true, + title: + "Partial floodfills can only be globalized when a segmentation annotation layer exists.", + }; + } + if (activeUser == null) { + return { + disabled: true, + title: "Partial floodfills can only be globalized as a registered user.", + }; + } + if (!features().jobsEnabled) { + return { + disabled: true, + title: "Partial floodfills can only be globalized when a webknossos-worker was set up.", + }; + } + + return { + disabled: false, + title: + "For this annotation some floodfill operations have not run to completion, because they covered a too large volume. webKnossos can finish these operations via a long-running job.", + }; +} diff --git a/frontend/javascripts/oxalis/view/right-border-tabs/starting_job_modals.tsx b/frontend/javascripts/oxalis/view/right-border-tabs/starting_job_modals.tsx index 7a6c8d1ef28..ac3f9afcf23 100644 --- a/frontend/javascripts/oxalis/view/right-border-tabs/starting_job_modals.tsx +++ b/frontend/javascripts/oxalis/view/right-border-tabs/starting_job_modals.tsx @@ -81,19 +81,21 @@ export function LayerSelection({ tracing, fixedLayerName, layerType, - setSelectedLayerName, + onChange, style, + value, }: { layers: APIDataLayer[]; tracing: HybridTracing; fixedLayerName?: string; layerType?: string; - setSelectedLayerName?: React.Dispatch>; style?: React.CSSProperties; + // onChange and value should not be renamed, because these are the + // default property names for controlled antd FormItems. + onChange?: React.Dispatch>; + value?: string | null; }): JSX.Element { - const onSelect = setSelectedLayerName - ? (layerName: string) => setSelectedLayerName(layerName) - : undefined; + const onSelect = onChange ? (layerName: string) => onChange(layerName) : undefined; const maybeLayerType = layerType || ""; const maybeSpace = layerType != null ? " " : ""; return ( @@ -108,6 +110,7 @@ export function LayerSelection({ disabled={fixedLayerName != null} onSelect={onSelect} style={style} + value={value} > {layers.map((layer) => { const readableName = getReadableNameOfVolumeLayer(layer, tracing) || layer.name; @@ -135,7 +138,7 @@ function LayerSelectionFormItem({ rules={[ { required: true, - message: `Please select the ${layerType} that should be used for this job.`, + message: `Please select the ${layerType} layer that should be used for this job.`, }, ]} hidden={layers.length === 1 && fixedLayerName == null}