1+ import { useQuery } from "@tanstack/react-query" ;
12import { isWorkflowAccessibleBySwitching } from "admin/api/organization" ;
23import { getVoxelyticsWorkflow } from "admin/rest_api" ;
34import BrainSpinner , { BrainSpinnerWithError } from "components/brain_spinner" ;
4- import { usePolling , useSearchParams , useWkSelector } from "libs/react_hooks" ;
5- import Toast from "libs/toast" ;
5+ import { useSearchParams , useWkSelector } from "libs/react_hooks" ;
66import sortBy from "lodash-es/sortBy" ;
77import { useEffect , useMemo , useState } from "react" ;
88import { useParams } from "react-router-dom" ;
99import {
10- type APIOrganization ,
1110 VoxelyticsRunState ,
1211 type VoxelyticsTaskConfig ,
1312 type VoxelyticsTaskConfigWithHierarchy ,
@@ -22,12 +21,6 @@ import TabTitle from "viewer/view/components/tab_title_component";
2221import TaskListView from "./task_list_view" ;
2322import { VX_POLLING_INTERVAL } from "./utils" ;
2423
25- type LoadingState =
26- | { status : "PENDING" }
27- | { status : "READY" }
28- | { status : "LOADING" }
29- | { status : "FAILED" ; error : Error ; organizationToSwitchTo ?: APIOrganization } ;
30-
3124function lexicographicalTopologicalSort (
3225 nodes : Array < VoxelyticsWorkflowDagNode > ,
3326 edges : Array < VoxelyticsWorkflowDagEdge > ,
@@ -318,12 +311,10 @@ function shouldCollapseId(id: string, expandedKeys: Record<string, boolean>): [s
318311}
319312
320313export default function WorkflowView ( ) {
321- const { workflowHash = "" } = useParams ( ) ;
314+ const { workflowHash = "" , runId } = useParams ( ) ;
322315 const { metatask } = useSearchParams ( ) ;
323316 const user = useWkSelector ( ( state ) => state . activeUser ) ;
324317
325- const [ loadingState , setLoadingState ] = useState < LoadingState > ( { status : "PENDING" } ) ;
326- const [ report , setReport ] = useState < VoxelyticsWorkflowReport | null > ( null ) ;
327318 // expandedMetaTaskKeys holds the meta tasks which should be expanded
328319 // in the left-side DAG. The right-side task listing will always show
329320 // all tasks (but in a hierarchical manner if meta tasks exist).
@@ -342,34 +333,36 @@ export default function WorkflowView() {
342333 setExpandedMetaTaskKeys ( sortedKeys ) ;
343334 } ;
344335
345- async function loadData ( ) {
346- try {
347- setLoadingState ( { status : "LOADING" } ) ;
348- let _report = parseReport ( await getVoxelyticsWorkflow ( workflowHash , null ) ) ;
349- if ( metatask != null ) {
350- // If a meta task is passed via a GET parameter,
351- // the entire report is filtered so that only the tasks of the given
352- // meta task are shown (left-hand as well as right-hand side).
353- _report = selectMetaTask ( _report , metatask ) ;
354- }
355- setReport ( _report ) ;
356- setLoadingState ( { status : "READY" } ) ;
357- } catch ( err ) {
358- try {
359- const organization =
360- user != null ? await isWorkflowAccessibleBySwitching ( workflowHash ) : null ;
361- setLoadingState ( {
362- status : "FAILED" ,
363- organizationToSwitchTo : organization ?? undefined ,
364- error : err as Error ,
365- } ) ;
366- } catch ( accessibleBySwitchingError ) {
367- Toast . error ( "Could not load workflow report." ) ;
368- console . error ( accessibleBySwitchingError ) ;
369- setLoadingState ( { status : "FAILED" , error : accessibleBySwitchingError as Error } ) ;
370- }
371- }
372- }
336+ const {
337+ data : report ,
338+ isLoading,
339+ isError,
340+ refetch,
341+ } = useQuery ( {
342+ queryKey : [ "voxelyticsWorkflow" , workflowHash ] ,
343+ queryFn : async ( ) => await getVoxelyticsWorkflow ( workflowHash , null ) ,
344+ // If a meta task is passed via a URL parameter, the entire report is filtered so that only the
345+ // tasks of the given meta task are shown (left-hand as well as right-hand side).
346+ select : ( data ) => {
347+ const parsedReport = parseReport ( data ) ;
348+ return metatask != null ? selectMetaTask ( parsedReport , metatask ) : parsedReport ;
349+ } ,
350+ refetchInterval : ( query ) => {
351+ const data = query . state . data ;
352+ return data == null || data . runs . some ( ( run ) => run . state === VoxelyticsRunState . RUNNING )
353+ ? ( VX_POLLING_INTERVAL ?? false )
354+ : false ;
355+ } ,
356+ staleTime : 0 , // disable caching
357+ gcTime : 0 , // disable garbage collection
358+ retry : false ,
359+ } ) ;
360+
361+ const { data : accessibleOrganization } = useQuery ( {
362+ queryKey : [ "voxelyticsWorkflowAccess" , workflowHash ] ,
363+ queryFn : ( ) => isWorkflowAccessibleBySwitching ( workflowHash ) ,
364+ enabled : isError && user != null ,
365+ } ) ;
373366
374367 useEffect ( ( ) => {
375368 if ( report != null ) {
@@ -391,23 +384,11 @@ export default function WorkflowView() {
391384 [ report ] ,
392385 ) ;
393386
394- usePolling (
395- loadData ,
396- // Only poll while the workflow is still running, but also load a report
397- // if it wasn't loaded before or the workflow hash changed
398- report == null ||
399- report . workflow . hash !== workflowHash ||
400- report . runs . some ( ( run ) => run . state === VoxelyticsRunState . RUNNING )
401- ? VX_POLLING_INTERVAL
402- : null ,
403- [ workflowHash ] ,
404- ) ;
405-
406- if ( loadingState . status === "FAILED" && user != null ) {
387+ if ( isError && user != null ) {
407388 return (
408389 < BrainSpinnerWithError
409390 gotUnhandledError = { false }
410- organizationToSwitchTo = { loadingState . organizationToSwitchTo }
391+ organizationToSwitchTo = { accessibleOrganization ?? undefined }
411392 entity = "workflow"
412393 />
413394 ) ;
@@ -425,8 +406,9 @@ export default function WorkflowView() {
425406 expandedMetaTaskKeys = { expandedMetaTaskKeys }
426407 onToggleExpandedMetaTaskKey = { handleToggleExpandedMetaTaskKey }
427408 openMetatask = { metatask }
428- onReload = { loadData }
429- isLoading = { loadingState . status === "LOADING" }
409+ runId = { runId ?? null }
410+ onReload = { refetch }
411+ isLoading = { isLoading }
430412 />
431413 </ div >
432414 ) ;
0 commit comments