@@ -44,6 +44,9 @@ type ControlButtonProps = {
4444} ;
4545
4646export const EMPTY_SUBMIT_TOOLTIP = "Empty annotations denied in this project" ;
47+ export const INCOMPLETE_SUBMIT_TOOLTIP = "Complete all regions before submitting" ;
48+ export const INCOMPLETE_UPDATE_TOOLTIP = "Complete all regions before updating" ;
49+ export const INCOMPLETE_ACCEPT_TOOLTIP = "Complete all regions before accepting" ;
4750
4851/**
4952 * Custom action button component, rendering buttons from store.customButtons
@@ -79,6 +82,7 @@ export const Controls = controlsInjector<{ annotation: MSTAnnotation }>(
7982 const [ isInProgress , setIsInProgress ] = useState ( false ) ;
8083 const disabled = ! annotationEditable || store . isSubmitting || historySelected || isInProgress ;
8184 const submitDisabled = store . hasInterface ( "annotations:deny-empty" ) && results . length === 0 ;
85+ const hasIncompleteRegions = annotation . hasIncompletePolygons ;
8286
8387 /** Check all things related to comments and then call the action if all is good */
8488 const handleActionWithComments = useCallback (
@@ -197,7 +201,7 @@ export const Controls = controlsInjector<{ annotation: MSTAnnotation }>(
197201
198202 // Also disable when overlap is reached (only when feature flag is enabled)
199203 const overlapDisabled = isFF ( FF_FIT_1304_STRICT_OVERLAP ) && store . overlapReached === true ;
200- const isDisabled = disabled || submitDisabled || overlapDisabled ;
204+ const isDisabled = disabled || submitDisabled || overlapDisabled || hasIncompleteRegions ;
201205
202206 const useExitOption = ! isDisabled && isNotQuickView ;
203207
@@ -237,14 +241,16 @@ export const Controls = controlsInjector<{ annotation: MSTAnnotation }>(
237241 } ;
238242
239243 if ( userGenerate || ( store . explore && ! userGenerate && store . hasInterface ( "submit" ) ) ) {
240- const title = overlapDisabled
241- ? store . overlapReachedMessage
242- : submitDisabled
243- ? EMPTY_SUBMIT_TOOLTIP
244- : "Save results: [ Ctrl+Enter ]" ;
244+ const title = hasIncompleteRegions
245+ ? INCOMPLETE_SUBMIT_TOOLTIP
246+ : overlapDisabled
247+ ? store . overlapReachedMessage
248+ : submitDisabled
249+ ? EMPTY_SUBMIT_TOOLTIP
250+ : "Save results: [ Ctrl+Enter ]" ;
245251
246252 buttons . push (
247- < ButtonTooltip key = "submit" title = { title } >
253+ < ButtonTooltip key = "submit" title = { title } className = "whitespace-nowrap max-w-none" >
248254 < div className = { cn ( "controls" ) . elem ( "tooltip-wrapper" ) . toClassName ( ) } >
249255 < ButtonGroup >
250256 < Button
@@ -291,46 +297,50 @@ export const Controls = controlsInjector<{ annotation: MSTAnnotation }>(
291297 // no changes were made over previously submitted version — no drafts, no pending changes
292298 const noChanges = isFF ( FF_REVIEWER_FLOW ) && ! history . canUndo && ! annotation . draftId ;
293299 const isUpdateDisabled = isDisabled || noChanges ;
294- const updateTitle = overlapDisabled
295- ? store . overlapReachedMessage
296- : noChanges
297- ? "No changes were made"
298- : "Update this task: [ Ctrl+Enter ]" ;
300+ const updateTitle = hasIncompleteRegions
301+ ? INCOMPLETE_UPDATE_TOOLTIP
302+ : overlapDisabled
303+ ? store . overlapReachedMessage
304+ : noChanges
305+ ? "No changes were made"
306+ : "Update this task: [ Ctrl+Enter ]" ;
299307 const button = (
300- < ButtonTooltip key = "update" title = { updateTitle } >
301- < ButtonGroup >
302- < Button
303- aria-label = "submit"
304- name = "submit"
305- className = "w-[150px]"
306- disabled = { isUpdateDisabled }
307- onClick = { async ( event ) => {
308- if ( ( event . target as HTMLButtonElement ) . classList . contains ( dropdownTrigger ) ) return ;
309- const selected = store . annotationStore ?. selected ;
310-
311- selected ?. submissionInProgress ( ) ;
312- await store . commentStore . commentFormSubmit ( ) ;
313- store . updateAnnotation ( ) ;
314- } }
315- data-testid = "bottombar-update-button"
316- >
317- { isUpdate ? "Update" : "Submit" }
318- </ Button >
319- { useExitOption ? (
320- < Dropdown . Trigger
321- alignment = "top-right"
322- content = { < SubmitOption onClickMethod = { store . updateAnnotation } isUpdate = { isUpdate } /> }
308+ < ButtonTooltip key = "update" title = { updateTitle } className = "whitespace-nowrap max-w-none" >
309+ < div className = { cn ( "controls" ) . elem ( "tooltip-wrapper" ) . toClassName ( ) } >
310+ < ButtonGroup >
311+ < Button
312+ aria-label = "submit"
313+ name = "submit"
314+ className = "w-[150px]"
315+ disabled = { isUpdateDisabled }
316+ onClick = { async ( event ) => {
317+ if ( ( event . target as HTMLButtonElement ) . classList . contains ( dropdownTrigger ) ) return ;
318+ const selected = store . annotationStore ?. selected ;
319+
320+ selected ?. submissionInProgress ( ) ;
321+ await store . commentStore . commentFormSubmit ( ) ;
322+ store . updateAnnotation ( ) ;
323+ } }
324+ data-testid = "bottombar-update-button"
323325 >
324- < Button
325- disabled = { isUpdateDisabled }
326- aria-label = "Update annotation"
327- data-testid = "bottombar-update-dropdown"
326+ { isUpdate ? "Update" : "Submit" }
327+ </ Button >
328+ { useExitOption ? (
329+ < Dropdown . Trigger
330+ alignment = "top-right"
331+ content = { < SubmitOption onClickMethod = { store . updateAnnotation } isUpdate = { isUpdate } /> }
328332 >
329- < IconChevronDown />
330- </ Button >
331- </ Dropdown . Trigger >
332- ) : null }
333- </ ButtonGroup >
333+ < Button
334+ disabled = { isUpdateDisabled }
335+ aria-label = "Update annotation"
336+ data-testid = "bottombar-update-dropdown"
337+ >
338+ < IconChevronDown />
339+ </ Button >
340+ </ Dropdown . Trigger >
341+ ) : null }
342+ </ ButtonGroup >
343+ </ div >
334344 </ ButtonTooltip >
335345 ) ;
336346
0 commit comments