@@ -5,19 +5,26 @@ import {
55 PageSectionVariants ,
66 Skeleton ,
77} from '@patternfly/react-core' ;
8- import React , { useEffect , useState } from 'react' ;
8+ import React , { useEffect , useMemo , useState } from 'react' ;
99import { translate as __ , documentLocale } from 'foremanReact/common/I18n' ;
1010import { useDispatch , useSelector } from 'react-redux' ;
1111import PageLayout from 'foremanReact/routes/common/PageLayout/PageLayout' ;
1212import PropTypes from 'prop-types' ;
1313import SkeletonLoader from 'foremanReact/components/common/SkeletonLoader' ;
1414import { stopInterval } from 'foremanReact/redux/middlewares/IntervalMiddleware' ;
1515import { useAPI } from 'foremanReact/common/hooks/API/APIHooks' ;
16+ import { STATUS as API_STATUS } from 'foremanReact/constants' ;
17+ import {
18+ selectAPIErrorMessage ,
19+ selectAPIHttpStatus ,
20+ selectAPIStatus ,
21+ } from 'foremanReact/redux/API/APISelectors' ;
1622
1723import { JobAdditionInfo } from './JobAdditionInfo' ;
1824import JobInvocationHostTable from './JobInvocationHostTable' ;
1925import JobInvocationOverview from './JobInvocationOverview' ;
2026import JobInvocationSystemStatusChart from './JobInvocationSystemStatusChart' ;
27+ import JobInvocationEmptyState from './JobInvocationEmptyState' ;
2128import JobInvocationToolbarButtons from './JobInvocationToolbarButtons' ;
2229import { getJobInvocation , getTask } from './JobInvocationActions' ;
2330import './JobInvocationDetail.scss' ;
@@ -51,9 +58,28 @@ const JobInvocationDetailPage = ({
5158 statusLabel === STATUS . SUCCEEDED ||
5259 statusLabel === STATUS . CANCELLED ;
5360 const autoRefresh = task ?. state === STATUS . PENDING || false ;
54- useAPI ( 'get' , currentPermissionsUrl , {
55- key : CURRENT_PERMISSIONS ,
56- } ) ;
61+ const { status : permissionsApiStatus } = useAPI (
62+ 'get' ,
63+ currentPermissionsUrl ,
64+ {
65+ key : CURRENT_PERMISSIONS ,
66+ }
67+ ) ;
68+ const jobInvocationApiStatus = useSelector ( state =>
69+ selectAPIStatus ( state , JOB_INVOCATION_KEY )
70+ ) ;
71+ const jobInvocationErrorMessage = useSelector ( state =>
72+ selectAPIErrorMessage ( state , JOB_INVOCATION_KEY )
73+ ) ;
74+ const permissionsErrorMessage = useSelector ( state =>
75+ selectAPIErrorMessage ( state , CURRENT_PERMISSIONS )
76+ ) ;
77+ const jobInvocationHttpStatus = useSelector ( state =>
78+ selectAPIHttpStatus ( state , JOB_INVOCATION_KEY )
79+ ) ;
80+ const permissionsHttpStatus = useSelector ( state =>
81+ selectAPIHttpStatus ( state , CURRENT_PERMISSIONS )
82+ ) ;
5783 const [ selectedFilter , setSelectedFilter ] = useState ( '' ) ;
5884
5985 const handleFilterChange = newFilter => {
@@ -88,6 +114,47 @@ const JobInvocationDetailPage = ({
88114 }
89115 } , [ dispatch , taskId ] ) ;
90116
117+ const apiFailed =
118+ permissionsApiStatus === API_STATUS . ERROR ||
119+ jobInvocationApiStatus === API_STATUS . ERROR ;
120+
121+ const backendErrorMessage = useMemo ( ( ) => {
122+ const parts = [ ] ;
123+ if ( jobInvocationApiStatus === API_STATUS . ERROR ) {
124+ const msg = jobInvocationErrorMessage ;
125+ if ( msg ) {
126+ parts . push ( msg ) ;
127+ }
128+ }
129+ if ( permissionsApiStatus === API_STATUS . ERROR ) {
130+ const msg = permissionsErrorMessage ;
131+ if ( msg ) {
132+ parts . push ( msg ) ;
133+ }
134+ }
135+ return parts . length ? parts . join ( '\n\n' ) : null ;
136+ } , [
137+ jobInvocationApiStatus ,
138+ permissionsApiStatus ,
139+ jobInvocationErrorMessage ,
140+ permissionsErrorMessage ,
141+ ] ) ;
142+
143+ const httpStatus =
144+ jobInvocationApiStatus === API_STATUS . ERROR
145+ ? jobInvocationHttpStatus
146+ : permissionsHttpStatus ;
147+
148+ if ( apiFailed ) {
149+ return (
150+ < JobInvocationEmptyState
151+ jobInvocationId = { id }
152+ httpStatus = { httpStatus }
153+ errorMessage = { backendErrorMessage }
154+ />
155+ ) ;
156+ }
157+
91158 const pageStatus =
92159 items . id === undefined
93160 ? STATUS_UPPERCASE . PENDING
0 commit comments